OpenCV4.5.5 16位有符号图像转兼容类型实现拼贴显示报错
问题背景
我正在尝试为当前为16s格式的图像制作拼贴图。cv2.imshow()不支持该图像类型,我暂时未找到正确的图像转换方式。
补充说明: 我已知cv2.imshow()支持除16u之外的其他图像类型,因此将图像转换为任意最易实现的兼容类型均可。
原实现代码如下:
import cv2 import numpy as np import glob import os import shutil from PIL import Image source_path = "C:/Users/source/path/" destination_path = "C:/Users/destination/path" #copy raw files only from source, and rename them in im1.png, im2.png etc format if os.path.exists(destination_path): print("destination file already exists") else: dir = os.mkdir(destination_path) files = glob.iglob(os.path.join(source_path, "*raw.png")) for file in files: if os.path.isfile(file): shutil.copy2(file, destination_path) #resize images and flip for file_name in os.listdir(destination_path): image = Image.open(os.path.join(destination_path, file_name)) new_dimensions = (50, 50) output = image.resize(new_dimensions, Image.ANTIALIAS).transpose(Image.FLIP_TOP_BOTTOM) output_file_name = os.path.join(destination_path, file_name) output.save(output_file_name, quality = 95) count=1 #rename the files for file_name in os.listdir(destination_path): source = destination_path + file_name destination = destination_path + "im" + str(count) + ".png" os.rename(source, destination) globals()["im" + str(count)] = destination count += 1 #create collage h_stack1 = np.hstack([im7,im6,im5,im4,im3,im2,im1]) h_stack2 = np.hstack([im8,im9,im10,im11,im12,im13,im14]) h_stack3 = np.hstack([im21,im20,im19,im18,im17,im16,im15]) h_stack4 = np.hstack([im22,im23,im24,im25,im26,im27,im28]) h_stack5 = np.hstack([im35,im34,im33,im32,im31,im30,im29]) h_stack6 = np.hstack([im36,im37,im38,im39,im40,im41,im42]) h_stack7 = np.hstack([im49,im48,im47,im46,im45,im44,im43]) v_stack = np.vstack([h_stack1,h_stack2,h_stack3,h_stack4,h_stack5,h_stack6,h_stack7]) cv2.imshow("collage",v_stack) cv2.imsave("collage.png",v_stack) cv2.waitKey(0) cv2.destroyAllWindows()
运行最后4行代码时触发如下报错:
Overload resolution failed:
- mat data type = 19 is not supported
- Expected Ptrcv::cuda::GpuMat for argument 'mat'
- Expected Ptrcv::UMat for argument 'mat'
问题原因
- 核心错误:通过
globals()动态生成的im1/im2...变量存的是图片文件的路径字符串,不是OpenCV可识别的图像矩阵对象,直接拿字符串做numpy拼接得到的是字符串数组,传给cv2接口自然会报数据类型不支持的错误(numpy字符串类型的dtype编号恰好为19,和报错信息完全对应)。 - 兼容问题:就算正确读取了图像,16s(16位有符号整数)格式直接传入
cv2.imshow/cv2.imwrite也存在兼容问题,转成通用的8位无符号整数(CV_8U,取值范围0-255)格式兼容性最好。 - 其他bug:路径拼接时没有加分隔符,会生成错误路径;保存图像的函数名写错,OpenCV没有
cv2.imsave接口,正确接口是cv2.imwrite。
修正方案
- 重命名文件时不再存路径字符串,所有文件重命名完成后,统一按文件名顺序读取图像,同步完成16s到8位格式的转换,把合法的图像矩阵存入列表备用。
- 所有路径拼接统一使用
os.path.join,避免分隔符缺失导致的路径错误。 - 修正保存图像的接口名。
- 按预设的排列顺序从图像列表中取对应矩阵做横向、纵向拼接。
修正后的完整代码:
import cv2 import numpy as np import glob import os import shutil from PIL import Image source_path = "C:/Users/source/path/" destination_path = "C:/Users/destination/path/" # 复制源目录下raw.png文件 if os.path.exists(destination_path): print("destination file already exists") else: os.mkdir(destination_path) files = glob.iglob(os.path.join(source_path, "*raw.png")) for file in files: if os.path.isfile(file): shutil.copy2(file, destination_path) # 调整图像尺寸、翻转 for file_name in os.listdir(destination_path): image = Image.open(os.path.join(destination_path, file_name)) new_dimensions = (50, 50) output = image.resize(new_dimensions, Image.ANTIALIAS).transpose(Image.FLIP_TOP_BOTTOM) output_file_name = os.path.join(destination_path, file_name) output.save(output_file_name, quality = 95) count = 1 # 重命名文件 for file_name in os.listdir(destination_path): source = os.path.join(destination_path, file_name) destination = os.path.join(destination_path, f"im{count}.png") os.rename(source, destination) count += 1 # 读取所有图像,转成cv2兼容的8位格式 img_list = [] for i in range(1, count): img_path = os.path.join(destination_path, f"im{i}.png") # 保留原始位深读取 img = cv2.imread(img_path, cv2.IMREAD_UNCHANGED) # 16s格式转8位无符号格式 if img.dtype == np.int16: img = img.astype(np.float32) # 像素值归一化到0-255区间 img = (img - img.min()) / (img.max() - img.min()) * 255 img = img.astype(np.uint8) img_list.append(img) # 按预设顺序拼接,列表索引从0开始,im1对应索引0,im7对应索引6 h_stack1 = np.hstack([img_list[6], img_list[5], img_list[4], img_list[3], img_list[2], img_list[1], img_list[0]]) h_stack2 = np.hstack([img_list[7], img_list[8], img_list[9], img_list[10], img_list[11], img_list[12], img_list[13]]) h_stack3 = np.hstack([img_list[20], img_list[19], img_list[18], img_list[17], img_list[16], img_list[15], img_list[14]]) h_stack4 = np.hstack([img_list[21], img_list[22], img_list[23], img_list[24], img_list[25], img_list[26], img_list[27]]) h_stack5 = np.hstack([img_list[34], img_list[33], img_list[32], img_list[31], img_list[30], img_list[29], img_list[28]]) h_stack6 = np.hstack([img_list[35], img_list[36], img_list[37], img_list[38], img_list[39], img_list[40], img_list[41]]) h_stack7 = np.hstack([img_list[48], img_list[47], img_list[46], img_list[45], img_list[44], img_list[43], img_list[42]]) v_stack = np.vstack([h_stack1,h_stack2,h_stack3,h_stack4,h_stack5,h_stack6,h_stack7]) cv2.imshow("collage",v_stack) cv2.imwrite("collage.png",v_stack) cv2.waitKey(0) cv2.destroyAllWindows()
内容的提问来源于stack exchange,提问作者user19042201
相关产品推荐
相关产品推荐

