def fuse_images(images,
                image_size=None,
                row=0,
                col=0,
                is_row_major=True,
                is_portrait=False,
                row_spacing=0,
                col_spacing=0,
                border_left=0,
                border_right=0,
                border_top=0,
                border_bottom=0,
                black_background=True):
    """Fuses a collection of images into an entire image.

    Args:
        images: A collection of images to fuse. Should be with shape [num,
            height, width, channels].
        image_size: This field is used to resize the image before fusion. `0`
            disables resizing. (default: None)
        row: Number of rows used for image fusion. If not set, this field will
            be automatically assigned based on `col` and total number of images.
            (default: None)
        col: Number of columns used for image fusion. If not set, this field
            will be automatically assigned based on `row` and total number of
            images. (default: None)
        is_row_major: Whether the input images should be arranged row-major or
            column-major. (default: True)
        is_portrait: Only active when both `row` and `col` should be assigned
            automatically. (default: False)
        row_spacing: Space between rows. (default: 0)
        col_spacing: Space between columns. (default: 0)
        border_left: Width of left border. (default: 0)
        border_right: Width of right border. (default: 0)
        border_top: Width of top border. (default: 0)
        border_bottom: Width of bottom border. (default: 0)

    Returns:
        The fused image.

    Raises:
        ValueError: If the input `images` is not with shape [num, height, width,
            width].
    """
    if images is None:
        return images

    if images.ndim != 4:
        raise ValueError(f'Input `images` should be with shape [num, height, '
                         f'width, channels], but {images.shape} is received!')

    num, image_height, image_width, channels = images.shape
    width, height = parse_image_size(image_size)
    height = height or image_height
    width = width or image_width
    row, col = get_grid_shape(num, row=row, col=col, is_portrait=is_portrait)
    fused_height = (
        height * row + row_spacing * (row - 1) + border_top + border_bottom)
    fused_width = (
        width * col + col_spacing * (col - 1) + border_left + border_right)
    fused_image = get_blank_image(
        fused_height, fused_width, channels=channels, is_black=black_background)
    images = images.reshape(row, col, image_height, image_width, channels)
    if not is_row_major:
        images = images.transpose(1, 0, 2, 3, 4)

    for i in range(row):
        y = border_top + i * (height + row_spacing)
        for j in range(col):
            x = border_left + j * (width + col_spacing)
            if height != image_height or width != image_width:
                image = cv2.resize(images[i, j], (width, height))
            else:
                image = images[i, j]
            fused_image[y:y + height, x:x + width] = image

    return fused_image
Fuses a collection of images into an entire image.

    Args:
        images: A collection of images to fuse. Should be with shape [num,
            height, width, channels].
        image_size: This field is used to resize the image before fusion. `0`
            disables resizing. (default: None)
        row: Number of rows used for image fusion. If not set, this field will
            be automatically assigned based on `col` and total number of images.
            (default: None)
        col: Number of columns used for image fusion. If not set, this field
            will be automatically assigned based on `row` and total number of
            images. (default: None)
        is_row_major: Whether the input images should be arranged row-major or
            column-major. (default: True)
        is_portrait: Only active when both `row` and `col` should be assigned
            automatically. (default: False)
        row_spacing: Space between rows. (default: 0)
        col_spacing: Space between columns. (default: 0)
        border_left: Width of left border. (default: 0)
        border_right: Width of right border. (default: 0)
        border_top: Width of top border. (default: 0)
        border_bottom: Width of bottom border. (default: 0)

    Returns:
        The fused image.

    Raises:
        ValueError: If the input `images` is not with shape [num, height, width,
            width].
    
utils/visualizer.py