Opencv实现多幅图像显示在同一窗口(基于Python)

关于Opencv如何将多幅图像显示在同一窗口,我查阅了许多资料,但是都是将两幅或多幅相同大小,相同通道数的图像拼接在一起显示,并不能将不同大小、通道数目的图像一起显示,这可以在python中可以利用numpy模块实现。因为图像的本质是一个多维矩阵,利用numpy的数组拼接功能可以实现将不同图像拼接成一个新矩阵,这样就像是同时显示了两幅图像。
例如:

import cv2
import numpy as np
# 读取图片
imgflower = cv2.imread("img_flower.jpg")
imgroi= cv2.imread("img_roi.jpg")
imgwomen = cv2.imread("img_women.jpg")

# 从本质上而言,图像是一个矩阵,我们可以用numpy拼接数组的方式,将两幅
# 图像拼接成一幅图像在显示出来,效果就像是同时显示了多幅图像

# 我们查看一下图像的大小信息,并将大小相同,通道相同的图片并排显示
print(imgflower.shape)
print(imgroi.shape)
print(imgwomen.shape)

# 水平组合
imghstack = np.hstack((imgroi, imgwomen))
# 垂直组合
imgvstack = np.vstack((imgroi, imgwomen))

# 显示一下看看
cv2.namedWindow("imgvstack")
cv2.imshow("imgvstack", imgvstack)

cv2.namedWindow("imghstack")
cv2.imshow("imghstack", imghstack)

cv2.destroyAllWindows()

结果如下:
Opencv实现多幅图像显示在同一窗口(基于Python)_第1张图片
Opencv实现多幅图像显示在同一窗口(基于Python)_第2张图片
Opencv实现多幅图像显示在同一窗口(基于Python)_第3张图片
我们分别拼接了两个大小、通道数目相同的图像。
那么如果,图像的大小或者通道数不同会怎样呢?

imghstack_ = imghstack = np.hstack((imgroi, imgflower))
# 会报错
# ValueError: all the input array dimensions for the concatenation axis must match exactly,
# but along dimension 0, the array at index 0 has size 512 and the array at index 1 has size 978

由此我们可以看到这种方法的一些弊端,首先就是它要求图像的通道及大小必须相同,其次就是当图像太大,或者数目较多时图像的显示会超出计算机的显示范围。当然我们也可以先对图像进行缩放处理再进行拼接显示,可是仅仅只是为了显示图像,这样的操作未免太繁琐。
为了实现任意数量、任意大小、任意通道的图像一起显示,我们可以编写一个函数,函数的实现过程不再赘述,下面是源码,注释的很详细:

# 定义函数,第一个参数是缩放比例,第二个参数是需要显示的图片组成的元组或者列表
def ManyImgs(scale, imgarray):
    rows = len(imgarray)         # 元组或者列表的长度
    cols = len(imgarray[0])      # 如果imgarray是列表,返回列表里第一幅图像的通道数,如果是元组,返回元组里包含的第一个列表的长度
    # print("rows=", rows, "cols=", cols)

    # 判断imgarray[0]的类型是否是list
    # 是list,表明imgarray是一个元组,需要垂直显示
    rowsAvailable = isinstance(imgarray[0], list)

    # 第一张图片的宽高
    width = imgarray[0][0].shape[1]
    height = imgarray[0][0].shape[0]
    # print("width=", width, "height=", height)

    # 如果传入的是一个元组
    if rowsAvailable:
        for x in range(0, rows):
            for y in range(0, cols):
                # 遍历元组,如果是第一幅图像,不做变换
                if imgarray[x][y].shape[:2] == imgarray[0][0].shape[:2]:
                    imgarray[x][y] = cv2.resize(imgarray[x][y], (0, 0), None, scale, scale)
                # 将其他矩阵变换为与第一幅图像相同大小,缩放比例为scale
                else:
                    imgarray[x][y] = cv2.resize(imgarray[x][y], (imgarray[0][0].shape[1], imgarray[0][0].shape[0]), None, scale, scale)
                # 如果图像是灰度图,将其转换成彩色显示
                if  len(imgarray[x][y].shape) == 2:
                    imgarray[x][y] = cv2.cvtColor(imgarray[x][y], cv2.COLOR_GRAY2BGR)

        # 创建一个空白画布,与第一张图片大小相同
        imgBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imgBlank] * rows   # 与第一张图片大小相同,与元组包含列表数相同的水平空白图像
        for x in range(0, rows):
            # 将元组里第x个列表水平排列
            hor[x] = np.hstack(imgarray[x])
        ver = np.vstack(hor)   # 将不同列表垂直拼接
    # 如果传入的是一个列表
    else:
        # 变换操作,与前面相同
        for x in range(0, rows):
            if imgarray[x].shape[:2] == imgarray[0].shape[:2]:
                imgarray[x] = cv2.resize(imgarray[x], (0, 0), None, scale, scale)
            else:
                imgarray[x] = cv2.resize(imgarray[x], (imgarray[0].shape[1], imgarray[0].shape[0]), None, scale, scale)
            if len(imgarray[x].shape) == 2:
                imgarray[x] = cv2.cvtColor(imgarray[x], cv2.COLOR_GRAY2BGR)
        # 将列表水平排列
        hor = np.hstack(imgarray)
        ver = hor
    return ver

我们来测试一下:

import cv2
import numpy as np
# 导入编写的函数,函数存放在OPencv文件夹下,文件名称为manyimgs
from OPencv_ import manyimgs

# 读取图片
imgflower = cv2.imread("img_flower.jpg")
imgroi= cv2.imread("img_roi.jpg")
imgwomen = cv2.imread("img_women.jpg")

# 第二种方法,调用我们自己编写的一个函数实现任意大小、任意通道数的图像堆叠显示
# 以原来的0.5倍并排显示两张图片
stackedimageh = manyimgs.ManyImgs(0.2, ([imgflower, imgwomen]))

# 垂直显示
stackedimagev = manyimgs.ManyImgs(0.2, ([imgflower, imgwomen], [imgwomen, imgflower]))

# 如果只有图片数量为奇数,并希望能够垂直显示,可以创建一个空白图像
Blankimg = np.zeros((200, 200), np.uint8)  # 大小可以任意函数会将其强制转换
stackedimageb = manyimgs.ManyImgs(0.2, ([imgflower, imgwomen], [imgwomen, Blankimg]))

cv2.namedWindow("stackedimageh")
cv2.imshow("stackedimageh", stackedimageh)

cv2.namedWindow("stackedimagev")
cv2.imshow("stackedimagev", stackedimagev)

cv2.namedWindow("stackedimageb")
cv2.imshow("stackedimageb", stackedimageb)

cv2.waitKey(0)
cv2.destroyAllWindows()

效果如下:
Opencv实现多幅图像显示在同一窗口(基于Python)_第4张图片
再多一些:
Opencv实现多幅图像显示在同一窗口(基于Python)_第5张图片

你可能感兴趣的:(python学习)