本节内容要用到opencv-python模块,请先行安装。本例程中使用到的图片保存在pictures子目录下。本例的任务是要将9张JPG格式图片按三行三列拼接成下述九宫格。
版权声明
本文可以在互联网上自由转载,但必须:注明出处(作者:海洋饼干叔叔)并包含指向本页面的链接。
本文不可以以纸质出版为目的进行改编、摘抄。
微实践:九宫格图像拼接
本节内容要用到opencv-python模块,请先行安装。本例程中使用到的图片保存在pictures子目录下。本例的任务是要将9张JPG格式图片按三行三列拼接成下述九宫格。
1 | #pictures9.py |
控制台输出:
1 | original: (960, 1280, 3) |
glob.glob(“pictures/*.jpg”)返回一个序列,该序列包括当前目录之pictures子目录下的所有扩展名为jpg的图片文件的文件名(含路径)。读者可以在上述循环中加上print(f)把这些文件名打出来看看。
imread()函数来自opencv-python扩展库,它读取一个图片,并返回一个多维数组。我们打印了这些多维数组的形状,典型如(960,1280,3):它表示对应图片高960个像素,宽1280个像素,每个像素由3个值构成,分别表示该像素红、绿、蓝三个通道的颜色值。请读者注意,本例中的9张图片的高度值并不相等。
img.shape[:2]取出了图像/多维数组的高度和宽度,分别赋值给h和w。所有的图片高、宽均存入heights、widths列表备用。所有的图片/多维数组均存入imgs列表备用。
显然,(960,1280)的图片尺寸对于九宫格拼接而言太大了,需要分别提取缩略图。
1 | #pictures9.py |
控制台输出:
1 | thumbnail: (265, 427, 3) |
我们首先获得了全部图像的最小高度 - min(heights)和最小宽度 - min(widths)。然后,遍历并逐一使用多维数组的切片下标语法提取缩略图:横纵向都从每3个像素中抽1个像素。根据打印出来的值,我们可以看到,所有的缩略图都是265 x 427个像素。
接下来,我们使用np.concatenate()函数将imgs列表中的9张图沿1轴拼接(横向拼接)至img。根据打印的结果,横向拼接后的图片尺寸为265 x 3843。imwrite()则将img存至文件”concatenated_1.jpg”。读者可以在项目目录中找到这个照片,如下:
下述代码及其执行结果可以帮助读者理解concatenate()函数的作用:可以看到,对于二维数组而言,沿0轴拼接相当于纵向延长数组,沿1轴拼接则相当于横向延长数组。
1 | #con.py |
执行结果:
1 | a= |
借助于concatenate()函数,我们可以先将图片0-2横向拼接,再将图片3-5横向拼接,接着再将图片6-8横向拼接。最后再将拼接结果纵向拼接,即得3x3的九宫格:
1 | #pictures9.py |
控制台输出:
1 | 3x3_0, shape: (795, 1281, 3) |
上述3x3_0.jpg应该与本例开始处的图片相同,该文件也存入了当前项目目录,读者自行查证。除了上面这个方法外,下面这个方法也可以达到相同的效果,但真的很难理解。在下述代码中,img1.swapaxes(1,2)将img1的1轴与2轴进行了交换。
1 | #方法2 |
控制台输出:
1 | 3x3_1, shape: (795, 1281, 3) |
读者可以查证3x3_1.jpg的最终效果。
读者可以试着执行下述代码来观察轴交换的效果:
1 | #swapaxes.py |
与多维数组操作有关的函数列表如下:
函数名 | 作用 | 函数名 | 作用 |
---|---|---|---|
concatenate() | 拼接多个数组 | vstack/hstack() | 沿0/1轴拼接数组 |
column_stack() | 按列连接多个一维数组 | split,array_split() | 将数组分为多段 |
transpose() | 重设轴的顺序 | swapaxes() | 交换两个轴的顺序 |
本文内容节选自作者编著的《Python编程基础及应用》(高等教育出版社)一书。
免费随书B站MOOC: