python下使用np.hstack进行图片拼接时报错 && 使用matplotlib展示图片的相关操作

python中调用np.hstack对两张图片进行水平拼接时提示:“ValueError: all the input array dimensions except for the concatenation axis must match exactly” 代码:import numpy as npimport cv2imgname1 = '1.jpg'imgname2 = '2...
摘要由CSDN通过智能技术生成

python中调用np.hstack对两张图片进行水平拼接时提示:“ValueError: all the input array dimensions except for the concatenation axis must match exactly” 代码:

import numpy as np
import cv2

imgname1 = '1.jpg'
imgname2 = '2.jpg'
img1 = cv2.imread(imgname1)
img2 = cv2.imread(imgname2)

hmerge = np.hstack((img1 , img2)) #水平拼接
cv2.imshow("merge", hmerge) #拼接显示为merge
cv2.waitKey(0)
cv2.destroyAllWindows()

此时python会报错:

Traceback (most recent call last):
  File "D:/xxxx/xxxx.py", line xx, in <module>
    hmerge = np.hstack((gray1, gray2)) #水平拼接
  File "D:\xxxx\venv\lib\site-packages\numpy\core\shape_base.py", line 280, in hstack
    return _nx.concatenate(arrs, 1)
ValueError: all the input array dimensions except for the concatenation axis must match exactly

这是因为拼接的两个图片的大小不一致,在使用numpy中的hstack()函数时,必须使所有输入数组具有相同的维数(数量和尺寸)才能进行拼接合并,否则就会提示上述错误。

解决方法:

1、利用opencv的其他方法,这里给出一些参考文档,不够都是使用C++或其他语言实现的,还没有找到python实现。

参考1:https://blog.csdn.net/u014581740/article/details/54983674(利用opencv将两张图像在同一窗口上显示,并在图片上显示文字)

参考2:opencv2 一个窗口显示多幅图片_cv2显示多张图片-CSDN博客(opencv2 一个窗口显示多幅图片)

参考3:https://my.oschina.net/u/1426828/blog/368838(OpenCV 在同一窗口显示多幅图片)

参考4:opencv 将两张图片显示到一幅图片中_opencv展示两张图-CSDN博客(opencv 将两张图片显示到一幅图片中)

2、使用matplotlib,能够将多张图片排列在一个窗口并且可以不用在意图片大小尺寸和颜色通道一样,具体又可以分为两种方法:一种是定位图片顶点坐标,相当于直接将图片拷贝到新的画布上;另一种是建立画布,按照类似matlab的subplot的样子显示图片。

(1)第一种方法为:

from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
 
 
# 1. 将两张icon图标显示在同一张图上面并保存;
def combine_photo(arr):
    #arr是一个列表,里面是两个图片的路径,例如["p1.png", 'p2.png']
    toImage = Image.new('RGB', (128, 64))
    img1 = Image.open(arr[0])
    img12 = Image.open(arr[1])
    toImage.paste(img1, (0, 0))
    toImage.paste(img12, (64, 0, 64 + img1.size[0], 0 + img1.size[1]))
    #函数描述:toImage:背景图片,paste()函数四个变量分别为:起始横轴坐标,起始纵轴坐标,横轴结束坐标,纵轴结束坐标;
    toImage.save( + "merged.png")
    plt.imshow(toImage)
    plt.title(level)
    #plt.show()

效果图:

 如图实现了将两个icon组合在一起的样式,其中,输入参数为两张图片的路径。参考文档:python两张图片显示在一张图上_plt怎么把两张图画在一起-CSDN博客(python两张图片显示在一张图上)

(2)使用matplotlib方法

#-*- coding: UTF-8 -*-
import matplotlib.pyplot as plt # plt 用于显示图片
import matplotlib.image as mpimg # mpimg 用于读取图片

img1=mpimg.imread('1.png')#读取图片
img2=mpimg.imread('2.png')#读取图片

plt.gcf().canvas.set_window_title('Test')#设置窗口名称
plt.gcf().suptitle("multi pic test")#设置图片标题

plt.subplot(121), plt.imshow(img1), plt.title("first")
plt.subplot(122), plt.imshow(img2), plt.title("second")

plt.show()

效果如下:

其中subplot()函数中传入的三个数字的含义分别为:行数、列数和序号(按照先行后列进行排序),需要先设定图片所在位置,然后才能使用imshow()展示在相应位置上,否则,后展示的图片会覆盖之前图片。subplot()的参数也可以写为:

plt.subplot(1, 2, 1), plt.imshow(img1), plt.title("first")
plt.subplot(1, 2, 2), plt.imshow(img2), plt.title("second")

此外,还需要说明的是:

①使用的imread方法只能读取png等几种格式的图片,不能读取jpg类型的图片,对于此问题,可以换用opencv来读取图片,不过由于opencv的初创者使用的是BGR模式,而现在一般使用的是RGB模式,所以需要将opencv中的BGR、GRAY格式转换为RGB,使matplotlib中能正常显示opencv的图像。具体代码如下:

#-*- coding: UTF-8 -*-
import cv2
import matplotlib.pyplot as plt # plt 用于显示图片

img1 = cv2.imread('7.jpg',cv2.IMREAD_COLOR)
img2 = cv2.imread('7.jpg',cv2.IMREAD_GRAYSCALE)
img3 = cv2.imread('7.jpg',cv2.IMREAD_UNCHANGED)
img4 = cv2.imread('7.jpg')

# 将opencv中的BGR、GRAY格式转换为RGB,使matplotlib中能正常显示opencv的图像
img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
#上条语句可以替换为img1 = img1[:, :, ::-1]
#img[:,:,0]表示图片的蓝色通道,熟悉Python的同学应该知道,对一个字符串s进行翻转用的是s[::-1],同样img[:,:,::-1]就表示BGR通道翻转,变成RGB

img2 = cv2.cvtColor(img2, cv2.COLOR_GRAY2RGB)
img3 = cv2.cvtColor(img3, cv2.COLOR_BGR2RGB)
img4 = cv2.cvtColor(img4, cv2.COLOR_BGR2RGB)

fig = plt.figure()
plt.gcf().canvas.set_window_title('Test')#设置窗口名称
plt.gcf().suptitle("multi pic test")#设置图片标题

plt.subplot(221)
plt.imshow(img1)
plt.title('img1')
plt.subplot(222)
plt.imshow(img2)
plt.title('img2')
plt.subplot(223)
plt.imshow(img3)
plt.title('img3')
plt.subplot(224)
plt.imshow(img4)
plt.title('img4')
plt.show()

效果图为:

②可以看到,使用这种方式后,对图片进行排布就变得非常简单方便了。但是如果仅仅需要展示图片的话,我们还需要去掉坐标轴,使用如下语句:

plt.xticks([])
plt.yticks([])

#使用上面两行代码将坐标比例尺置空,或者下面一行代码关闭坐标轴,都可以实现想要的效果
axis('off')

加上上述代码后:

#-*- coding: UTF-8 -*-
import cv2
import matplotlib.pyplot as plt # plt 用于显示图片

img1 = cv2.imread('7.jpg')
img2 = cv2.imread('11.jpg')

# 将opencv中的BGR、GRAY格式转换为RGB,使matplotlib中能正常显示opencv的图像
img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)

fig = plt.figure()
plt.gcf().canvas.set_window_title('Test')#设置窗口名称
plt.gcf().suptitle("multi pic test")#设置图片标题

plt.subplot(121)
plt.imshow(img1)
plt.title('img1')
plt.xticks([])
plt.yticks([])

plt.subplot(122)
plt.imshow(img2)
plt.title('img2')
plt.xticks([])
plt.yticks([])

plt.show()

效果为:

③可以看到,效果已经美观了很多,但还是有一些问题,我们可以使用下面的代码调整子图间距和整体空白:

fig.tight_layout()#调整整体空白
plt.subplots_adjust(wspace =0, hspace =0)#调整子图间距

④此外,观察到生成的图片在清晰度上还有一些问题,我们可以使用一些语句对清晰度进行调整:

plt.rcParams['figure.figsize'] = (12.5, 4.0) # 设置figure_size尺寸
# 默认的像素:[6.0,4.0],分辨率为100,图片尺寸为 600&400
# 设置figsize可以在不改变分辨率情况下改变比例
#或者使用语句:plt.figure(figsize=(12.5,4)) 
#或者使用语句:plt.figsize(12.5, 4)

plt.rcParams['savefig.dpi'] = 300 #设置保存时的图片分辨率
plt.rcParams['figure.dpi'] = 300 #设置绘制时的图片分辨率
# 指定dpi=200,图片尺寸为 1200*800
# 指定dpi=300,图片尺寸为 1800*1200

plt.rcParams['image.interpolation'] = 'nearest' # 设置 interpolation style
plt.rcParams['image.cmap'] = 'gray' # 设置 颜色 style

⑤以上的设置基本都是针对显示图片时,如果仅对保存文件设置而不需要查看图片,可以使用以下语句:

plt.savefig('1.png', bbox_inches='tight', dpi=300) #去掉多余的padding空白区域,并按指定分辨率保存

最终效果:

参考文献:

python将多幅图片显示在一张图片上:

python将多幅图片显示在一张图片上_python多张图片同时显示-CSDN博客

如何使用opencv和matplotlib把多个图片显示在一个窗体内:

如何使用opencv和matplotlib把多个图片显示在一个窗体内_opencv 多图显示-CSDN博客

python使用opencv或matplotlib把多张图片显示在一个窗口内的方法:

python使用opencv或matplotlib把多张图片显示在一个窗口内的方法_python opencv连续显示一个文件夹下的图片-CSDN博客

基于Python中的matplotlib图片的灰度处理:

基于Python中的matplotlib图片的灰度处理_python图像灰度范围标准化软件包-CSDN博客

如有不当之处,欢迎指正交流!

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Python实现图片拼接并输出全景图片的方法如下: 首先,需要安装和导入必要的库,如numpy、opencvmatplotlib。 ```python import cv2 import numpy as np from matplotlib import pyplot as plt ``` 然后,需要加载待拼接图片,将其转换为灰度图,并将其特征进行检测和描述。 ```python # 加载待拼接图片 image1 = cv2.imread('image1.jpg') image2 = cv2.imread('image2.jpg') # 转换为灰度图 gray1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) # 创建SIFT对象用于特征检测和描述 sift = cv2.SIFT_create() # 检测和描述特征点 kp1, des1 = sift.detectAndCompute(gray1, None) kp2, des2 = sift.detectAndCompute(gray2, None) ``` 接下来,需要使用特征匹配算法(如FLANN)来找到两幅图片中的匹配点。 ```python # 创建FLANN匹配器 flann = cv2.FlannBasedMatcher() # 进行特征匹配 matches = flann.knnMatch(des1, des2, k=2) # 选择优秀的匹配点 good_matches = [] for m, n in matches: if m.distance < 0.7 * n.distance: good_matches.append(m) ``` 然后,需要将匹配点对应的像素坐标提取出来,并进行透视变换以实现图片拼接。 ```python # 提取匹配点对应的像素坐标 src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2) dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2) # 透视变换 M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) result = cv2.warpPerspective(image1, M, (image1.shape[1] + image2.shape[1], image1.shape[0])) result[0:image2.shape[0], 0:image2.shape[1]] = image2 ``` 最后,使用matplotlib库将拼接好的全景图显示出来并保存。 ```python # 显示和保存全景图 plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB)) plt.xticks([]) plt.yticks([]) plt.show() cv2.imwrite('panorama.jpg', result) ``` 以上是使用Python实现图片拼接并输出全景图片的基本步骤,根据实际情况可以进行相应的调整和优化。 ### 回答2: Python实现图片拼接,输出全景图片的一种方法是使用OpenCV库。以下是大致的步骤描述: 1. 首先,我们需要将多张图片加载进来作为拼接的原始图片使用OpenCV的`cv2.imread()`函数可以读取图片。假设我们有n张图片,将它们存储在一个列表中。 2. 接下来,我们需要找到每张图片的特征点。使用OpenCV的`cv2.ORB_create()`函数可以初始化一个ORB(Oriented FAST and Rotated BRIEF)对象,用于检测特征点。然后,使用`detectAndCompute()`函数找到每张图片的关键点和特征描述符。 3. 然后,我们需要在每个图像对之间找到匹配的特征点。使用OpenCV的`cv2.BFMatcher()`函数初始化一个Brute-Force匹配器对象,并使用`knnMatch()`函数进行特征点匹配。 4. 接下来,我们需要根据匹配的特征点来计算透视变换矩阵。使用OpenCV的`cv2.findHomography()`函数来计算透视变换。该函数接受匹配的关键点作为输入,并返回一张图像到另一张图像的透视变换矩阵。 5. 然后,我们使用透视变换矩阵将图像进行拼接使用OpenCV的`cv2.warpPerspective()`函数,传入待拼接的图像和透视变换矩阵,可以对图像进行透视变换。 6. 最后,我们将拼接后的图像保存为全景图片使用OpenCV的`cv2.imwrite()`函数将拼接后的图像保存到指定路径。 以上是简要的步骤描述,实际实现中还需要考虑一些细节问题,并根据具体的需求进行适当的调整。 ### 回答3: Python使用OpenCV库可以实现图片拼接,从而输出全景图片。以下是一个简单的代码示例: ```python import cv2 import numpy as np def stitch_images(images): # 初始化拼接器 stitcher = cv2.Stitcher_create() # 进行拼接 status, panorama = stitcher.stitch(images) # 返回拼接结果(status表示拼接成功与否) return panorama, status # 读取需要拼接图片 image1 = cv2.imread('image1.jpg') image2 = cv2.imread('image2.jpg') # 将图片放入列表中 images = [image1, image2] # 调用拼接函数 panorama, status = stitch_images(images) # 判断拼接结果是否成功 if status == cv2.Stitcher_OK: # 保存全景图片 cv2.imwrite('panorama.jpg', panorama) # 显示全景图片 cv2.imshow('Panorama Image', panorama) cv2.waitKey(0) cv2.destroyAllWindows() else: print("拼接失败") ``` 该代码首先导入了需要用到的库,然后定义了一个`stitch_images`函数,该函数利用OpenCV的`Stitcher_create`函数创建了一个拼接器对象,然后调用`stitch`函数对图片进行拼接。最后,根据拼接的结果进行判断,如果成功则保存全景图片,并显示出来,否则输出拼接失败的信息。 需要注意的是,该代码只是一个基本示例,对于复杂的场景可能需要进一步调整参数或使用其他技术来提高拼接的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值