如果需要处理的原图及代码,请移步小编的GitHub地址
传送门:请点击我
如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice
本来不想碎碎念,但是我已经在图像后缀上栽倒两次了。而且因为无意犯错,根本找不到问题。不论是在深度学习的语义分割中,还是在图像处理的软件(Halcon, Cognex)中都载过跟头,于是痛定思痛,决定将自己的经验写进这篇博客中,如果看到这篇的看官,希望不要再犯了。
问题1:乱修改图像后缀名称,部分软件会报错(halcon error #5580:PNG:file is not a PNG file)
首先是下面的报错,因为openCV使用多了,我们经常会通过cv2.imread()加载出三通道的图像,所以默认图像都是BGR的,无论图像是png, bmp 还是 jpg。反正都可以读出三通道的,即使有时候无意将图像后缀命名为png或者jpg(或者我们网上下载的数据集中被修改了后缀),我们都不在意。但是实际上部分软件不会像opencv自动处理,我在这里就报错了。
具体深入下去,就是下图,实际上图像后缀是jpg,但是我拿到的数据是png,而我直接喂入软件就报错如上:
实际上这两个图像都是png图像,但是可能就会出现有些人误命名,将其图像后缀命名为jpg。这就导致了上面的问题。
我们具体分析,当我们将图像后缀从.png修改为.jpg时,实际上并没有改变图像的编码方式和文件结构。而如我上面所说,OpenCV是一个功能强大的计算机视觉库,它可以根据文件的实际内容来识别图像格式,而不仅仅依赖于文件后缀。因此,OpenCV能够读取被错误命名的图像文件。
然而,其他一些软件可能只依赖于文件后缀来确定图像格式,而不会尝试解析文件内容。当你将图像后缀从.png修改为.jpg时,这些软件可能会尝试按照JPEG格式去解析该文件,但是由于文件实际上是一个PNG格式的图像,所以会报错并指出文件不是一个有效的PNG文件。
所以要正确地处理图像文件,建议使用正确的文件后缀来反映实际的图像格式。这样可以确保不同的软件能够正确地解析和处理图像文件。
问题2:图像随便保存为jpg,结果mask结果对不上
当我写这篇博客的时候,我发现也有网友有同样的问题,哈哈哈,于是我就更坚决了自己要写这个的原因。
首先复现一下下面问题,并解释一下。
我们就将输出的图像保存为图像(即jpg和png),然后读取出来,看看结果:
import sys import os import numpy as np def count_pixel_values(image): count_res = {} # 统计像素值数量 pixel_counts = np.bincount(image.flatten()) # 显示结果 for pixel_value, count in enumerate(pixel_counts): if count > 0: count_res[pixel_value] = count return count_res # 读取一张图像,将其转换为灰度图 image = cv2.imread(r"./Abyssinian_1.png", 0) # 创建二值图像 binary_image = np.zeros_like(image, dtype=np.uint8) binary_image[image == 1] = 0 # 像素值1对应0像素 binary_image[image == 2] = 125 # 像素值2对应125像素 binary_image[image == 3] = 255 # 像素值3对应255像素 # 1, 我将二值图结果保存为jpg 和png,我们分别看看 # cv2.imwrite(r"./cat.png", binary_image) # cv2.imwrite(r"./cat.jpg", binary_image) # 2, 我分别打开png 和 jpg 的图像 png_mask = cv2.imread(r"./cat.png", 0) jpg_mask = cv2.imread(r"./cat.jpg", 0) print(np.array_equal(png_mask, binary_image), np.sum(png_mask != binary_image)) pixel_counts_png = count_pixel_values(png_mask) print(pixel_counts_png) print(np.array_equal(jpg_mask, binary_image), np.sum(jpg_mask != binary_image)) pixel_counts_jpg = count_pixel_values(jpg_mask) print(pixel_counts_jpg) # 使用sys.getsizeof()函数来获取图像对象的大小 # 使用os.path.getsize()函数来获取图像文件的大小 binary_image_memory_size = sys.getsizeof(binary_image) png_mask_memory_size = sys.getsizeof(png_mask) jpg_mask_memory_size = sys.getsizeof(jpg_mask) print("二值图图像内存大小: {} 字节".format(binary_image_memory_size)) print("jpg二值图图像内存大小: {} 字节".format(png_mask_memory_size)) print("png二值图图像内存大小: {} 字节".format(jpg_mask_memory_size)) binary_image_file_size = os.path.getsize(r"./Abyssinian_1.png") png_mask_file_size = os.path.getsize(r"./cat.png") jpg_mask_file_size = os.path.getsize(r"./cat.jpg") print("二值图图像文件大小: {} 字节".format(binary_image_file_size)) print("jpg二值图图像文件大小: {} 字节".format(png_mask_file_size)) print("png二值图图像文件大小: {} 字节".format(jpg_mask_file_size)) """ True 0 {0: 22938, 125: 198766, 255: 18296} False 8258 {0: 21455, 1: 701, 2: 414, 3: 234, 4: 95, 5: 27, 6: 7, 7: 4, 8: 1, 119: 2, 120: 27, 121: 147, 122: 259, 123: 517, 124: 839, 125: 195208, 126: 879, 127: 449, 128: 258, 129: 123, 130: 38, 131: 17, 132: 3, 248: 7, 249: 12, 250: 71, 251: 170, 252: 421, 253: 911, 254: 1625, 255: 15079} """