imwrite或者imread时像素值发生变化

我想读取元素图片,并进行像素值拉伸。代码中是直接将像素值乘以5.

for file in os.listdir(data_dir):                   ###最多读取两级目录找到图片
    if os.path.isdir(os.path.join(data_dir,file)):
        #print("it's a directory")
        if os.path.exists(os.path.join(save_dir,file)):
            #os.rmdir(os.path.join(save_dir,file)) #只能删除空目录
            shutil.rmtree(os.path.join(save_dir,file)) #空目录、有内容的目录都可以删
            os.mkdir(os.path.join(save_dir,file))
        else:
            os.mkdir(os.path.join(save_dir,file))
        for sub_file in os.listdir(os.path.join(data_dir,file)):
            if file is not "XLT_ASA01_IIT_L01_STP_20180308184752.png":  ####该图片是问题图片
            #if sub_file != "XLT_ASA01_IIT_L01_STP_20180308184752.png":
                img = cv.imread(os.path.join(os.path.join(data_dir,file),sub_file),2)
                print(type(img),img.dtype)
                #img = cv2.imread('/home/zhongjia/plasmabubble/scale_test.png',2)
                #print(type(img),img.shape,img.dtype)
                #plt.figure()
                #plt.imshow(img,cmap='Greys_r')
                #print(img.max())
                print(img.max(),img.min())
                print(img[50][50])
                img = img*5.0  ### imread输出的uint8变为float64
                print(img[50][50],img.shape,img.max(),img.min(),img.dtype)
                #img = np.array(img,dtype='uint16')
                #print(img[50][50],img.shape,img.max(),img.min(),img.dtype)
                ### medianBlur(InputArray src, OutputArray dst, int ksize),
                #InputArray src: 输入图像,图像为1、3、4通道的图像,当模板尺寸为3或5时,图像深度只能为CV_8U、CV_16U、CV_32F中的一个
                #img = (img-img.min())*(255/(img.max()-img.min()))
                #print(img[50][50])
                #print(type(img),img.dtype)
                cv.imwrite(os.path.join(os.path.join(save_dir,file),'pad_'+sub_file),img)
                img = cv.imread(os.path.join(os.path.join(save_dir,file),'pad_'+sub_file))
                print(img.max(),img.min(),img.dtype,img.shape)
                print(img[50][50])
                img = np.array(img,dtype='uint8')
                print(img[50][50])
                img_lvbo = cv.medianBlur(img, 5)
                print(img.max(),img.min())

                #print(img.max())
                cv.imwrite(os.path.join(os.path.join(save_dir,file),'lvbo_'+sub_file),img_lvbo)

输出结果:

可以看到原图最大最小值127,6 ,uint8

乘以5后变为最大最小值635,30 ,float64, 第50行50列元素50

经过imwrite和imread后,最大值255,最小值不变,第50行50列元素50不变,通道由1变为3,float64变为uint8.

修改代码img*1.0:

for sub_file in os.listdir(os.path.join(data_dir,file)):
            if file is not "XLT_ASA01_IIT_L01_STP_20180308184752.png":  ####该图片是问题图片
            #if sub_file != "XLT_ASA01_IIT_L01_STP_20180308184752.png":
                img = cv.imread(os.path.join(os.path.join(data_dir,file),sub_file),2)
                print(type(img),img.dtype)
                #img = cv2.imread('/home/zhongjia/plasmabubble/scale_test.png',2)
                #print(type(img),img.shape,img.dtype)
                #plt.figure()
                #plt.imshow(img,cmap='Greys_r')
                #print(img.max())
                print(img.max(),img.min())
                print(img[50][50])
                img = img*1.0  ### imread输出的uint8变为float64
                print(img[50][50],img.shape,img.max(),img.min(),img.dtype)
                #img = np.array(img,dtype='uint16')
                #print(img[50][50],img.shape,img.max(),img.min(),img.dtype)
                ### medianBlur(InputArray src, OutputArray dst, int ksize),
                #InputArray src: 输入图像,图像为1、3、4通道的图像,当模板尺寸为3或5时,图像深度只能为CV_8U、CV_16U、CV_32F中的一个
                #img = (img-img.min())*(255/(img.max()-img.min()))
                #print(img[50][50])
                #print(type(img),img.dtype)
                cv.imwrite(os.path.join(os.path.join(save_dir,file),'pad_'+sub_file),img)
                img = cv.imread(os.path.join(os.path.join(save_dir,file),'pad_'+sub_file))
                print(img.max(),img.min(),img.dtype,img.shape)
                print(img[50][50])
                img = np.array(img,dtype='uint8')
                print(img[50][50])
                img_lvbo = cv.medianBlur(img, 5)
                print(img.max(),img.min())
                #print(img.max())
                cv.imwrite(os.path.join(os.path.join(save_dir,file),'lvbo_'+sub_file),img_lvbo)

输出结果:

可以看到imwrite和imread没有改变像素值,仅仅有uint8变为float64.

从结果看,那么只有超过255的值会发生像素变化,究竟是imwrite引起的还是imread函数引起的。

参考https://blog.csdn.net/oukohou/article/details/82378552,说是报错的图像格式引起的。

但是我这里读取和保存的都是png格式,不应该是格式问题。

而当我仅仅改变读取像素值为uint16时,

for sub_file in os.listdir(os.path.join(data_dir,file)):
            if file is not "XLT_ASA01_IIT_L01_STP_20180308184752.png":  ####该图片是问题图片
            #if sub_file != "XLT_ASA01_IIT_L01_STP_20180308184752.png":
                img = cv.imread(os.path.join(os.path.join(data_dir,file),sub_file),2)
                print(type(img),img.dtype)
                #img = cv2.imread('/home/zhongjia/plasmabubble/scale_test.png',2)
                #print(type(img),img.shape,img.dtype)
                #plt.figure()
                #plt.imshow(img,cmap='Greys_r')
                #print(img.max())
                print(img.max(),img.min())
                print(img[50][50])
                img = img*1.0  ### imread输出的uint8变为float64
                print(img[50][50],img.shape,img.max(),img.min(),img.dtype)
                img = np.array(img,dtype='uint16')
                #print(img[50][50],img.shape,img.max(),img.min(),img.dtype)
                ### medianBlur(InputArray src, OutputArray dst, int ksize),
                #InputArray src: 输入图像,图像为1、3、4通道的图像,当模板尺寸为3或5时,图像深度只能为CV_8U、CV_16U、CV_32F中的一个
                #img = (img-img.min())*(255/(img.max()-img.min()))
                #print(img[50][50])
                #print(type(img),img.dtype)
                cv.imwrite(os.path.join(os.path.join(save_dir,file),'pad_'+sub_file),img)
                img = cv.imread(os.path.join(os.path.join(save_dir,file),'pad_'+sub_file))
                print(img.max(),img.min(),img.dtype,img.shape)
                print(img[50][50])
                img = np.array(img,dtype='uint8')
                print(img[50][50])
                img_lvbo = cv.medianBlur(img, 5)
                print(img.max(),img.min())
                #print(img.max())
                cv.imwrite(os.path.join(os.path.join(save_dir,file),'lvbo_'+sub_file),img_lvbo)

最大值最小值结果就发生了变化。

所以应该是矩阵在存为图像或者读取时,数据类型引起的错误。可见imwrite或者imread不能自动将数据线性压缩到0-255,而是会发生截断,大于255的值赋值为255.

通过查看imread函数API:

imread()参数说明
2   cv2.IMREAD_UNCHANGED = -1, //返回原通道原深度图像
3   cv2.IMREAD_GRAYSCALE = 0, //返回单通道(灰度),8位图像
4   cv2.IMREAD_COLOR = 1, //返回三通道,8位图像,为默认参数
5   cv2.IMREAD_ANYDEPTH = 2, //返回单通道图像。如果原图像深度为16/32 位,则返回原深度,否则转换为8位
6   cv2.IMREAD_ANYCOLOR = 4, //返回原通道,8位图像。

读取原始位深图是imread参数设置为2

修改代码:

for sub_file in os.listdir(os.path.join(data_dir,file)):
            if file is not "XLT_ASA01_IIT_L01_STP_20180308184752.png":  ####该图片是问题图片
            #if sub_file != "XLT_ASA01_IIT_L01_STP_20180308184752.png":
                img = cv.imread(os.path.join(os.path.join(data_dir,file),sub_file),2)
                print(type(img),img.dtype)
                #img = cv2.imread('/home/zhongjia/plasmabubble/scale_test.png',2)
                #print(type(img),img.shape,img.dtype)
                #plt.figure()
                #plt.imshow(img,cmap='Greys_r')
                #print(img.max())
                print(img.max(),img.min())
                print(img[50][50])
                img = img*5.0  ### imread输出的uint8变为float64
                print(img[50][50],img.shape,img.max(),img.min(),img.dtype)
                #img = np.array(img,dtype='uint16')
                #print(img[50][50],img.shape,img.max(),img.min(),img.dtype)
                ### medianBlur(InputArray src, OutputArray dst, int ksize),
                #InputArray src: 输入图像,图像为1、3、4通道的图像,当模板尺寸为3或5时,图像深度只能为CV_8U、CV_16U、CV_32F中的一个
                #img = (img-img.min())*(255/(img.max()-img.min()))
                #print(img[50][50])
                #print(type(img),img.dtype)
                cv.imwrite(os.path.join(os.path.join(save_dir,file),'pad_'+sub_file),img)
                img = cv.imread(os.path.join(os.path.join(save_dir,file),'pad_'+sub_file),2)
                print(img.max(),img.min(),img.dtype,img.shape)
                print(img[50][50])
                img = np.array(img,dtype='uint8')
                print(img[50][50])
                img_lvbo = cv.medianBlur(img, 5)
                print(img.max(),img.min())
                #print(img.max())
                cv.imwrite(os.path.join(os.path.join(save_dir,file),'lvbo_'+sub_file),img_lvbo)

imread读取原始位uint8,所以float64的矩阵通过imwrite函数存储是发生了改变。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以通过以下步骤实现将经过位移、旋转等化后的二值图像转化为原来对应位置像素值的程序: 1. 首先读取换后的二值图像和原始图像。 2. 对换后的二值图像进行反换,即将换后的坐标转换为原始坐标。 3. 遍历反换后的二值图像的每个像素,找到对应原始图像中的像素值,并将其赋值给新的图像数组。 4. 将新的图像数组保存为图像文件。 下面是一个示例程序,其中使用了OpenCV库来读取和保存图像文件: ```python import cv2 import numpy as np # 读取换后的二值图像和原始图像 img_transformed = cv2.imread('transformed_image.png', cv2.IMREAD_GRAYSCALE) img_original = cv2.imread('original_image.png', cv2.IMREAD_GRAYSCALE) # 获取换后的图像尺寸 height, width = img_transformed.shape[:2] # 定义新的图像数组 img_restored = np.zeros((height, width), dtype=np.uint8) # 定义反换矩阵 M_inv = cv2.invertAffineTransform(M) # 对换后的二值图像进行反img_restored = cv2.warpAffine(img_transformed, M_inv, (width, height)) # 遍历反换后的二值图像的每个像素,找到对应原始图像中的像素值 for i in range(height): for j in range(width): if img_restored[i, j] > 0: img_restored[i, j] = img_original[i, j] # 将新的图像数组保存为图像文件 cv2.imwrite('restored_image.png', img_restored) ``` 注意,上述代码中的换矩阵M_inv需要根据具体的换方式进行计算。如果是旋转换,可以使用cv2.getRotationMatrix2D()函数来获取换矩阵;如果是仿射换,可以使用cv2.getAffineTransform()函数来获取换矩阵。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值