openCV+pyplot:显示图像颜色不对应

本来是想写一个简单的掩模例程后来出了些问题,记录一下过程:

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

file = 'lenargb.bmp'
pic = cv.imread(file)

pic = cv.cvtColor(pic, cv.COLOR_RGB2BGR)
cv.imshow('image', pic)
cv.waitKey(0)
cv.destroyAllWindows()
# 生成一个长宽和原图像一样的全黑图    
mask = np.zeros(pic.shape[:2],np.uint8) 
#print(mask.shape) #(512,512)
# 把感兴趣的地方变白
mask[200:300,200:300] = 255 
#show_pic('mask',mask)
# 与操作
masked_pic = cv.bitwise_and(pic,pic,mask=mask) 

# 看原图和掩码过后的图的直方图
hist_full = cv.calcHist([pic],[0],None,[256],[0,256])
hist_mask = cv.calcHist([pic],[0],mask,[256],[0,256])

plt.subplot(221),plt.imshow(pic,'gray')
plt.subplot(222),plt.imshow(mask,'gray')
plt.subplot(223),plt.imshow(masked_pic,'gray')
plt.subplot(224),plt.plot(hist_full),plt.plot(hist_mask)
plt.show()

发现最后输出的图片为蓝色。

试一下将BGR转变为RGB显示图像:

OpenCV中默认使用BGR颜色空间显示图像

首先我设定了一个函数,把bgr三个通道分离,再用gbr的顺序合并:

def changeBGRtoRGB(img):
    all_channel = img.shape
    if all_channel == 3:
        b, g, r = cv.split(img)
        img = cv.merge([r, g, b])
    return img

cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()

会发现还是显示的原图。

原因:即使已经将BGR通道转换为RGB通道,如果没有指定 cv2.imshow 函数使用的颜色空间,则它仍然会将图像解释为BGR图像,并以此显示。

实际上imshow时改一下里面的参数就行了:

cv.imshow('image', cv.cvtColor(img, cv.COLOR_RGB2BGR))

无需定义函数。此时图片为:

 运行完整代码,输出图1 pic 及图3 masked_pic 为原图和原图掩模(彩色的),但是我输入的指令是plt.imshow(pic,'gray'),为什么还是彩色呢?

(1)可能是因为图像的数据类型不正确。

plt.imshow函数在显示图像时,需要将图像的数据类型转换为浮点型(float)或无符号整型(uint8)。如果图像的数据类型不正确,可能会导致显示不正确。可以使用 dtype 参数指定要使用的数据类型。

以掩模后的图像为例:

plt.imshow(masked_pic, cmap='gray', dtype='uint8')

出现错误:'AxesImage' object has no property 'dtype'

dytpe 参数是用于指定数组的数据类型的,而不是用于 plt.imshow 函数的参数。如果需要指定图像的数据类型,可以在调用 plt.imshow 函数之前,使用 astype 方法将图像的数据类型转换为正确的类型。

masked_pic = masked_pic.astype('uint8')
plt.imshow(masked_pic, cmap='gray')

结果依旧为彩图。

(2)可能是因为图像的像素值范围不正确。灰度图像的像素值应该在0到255之间,如果像素值范围不正确,可能会导致显示不正确。可以使用 np.clip 函数将像素值限制在0到255之间.

masked_pic = np.clip(masked_pic, 0, 255).astype('uint8')
plt.imshow(masked_pic, cmap='gray')

结果依旧为彩图。

最终发现:

这是因为 cmap = 'gray' 参数只能将单通道图像(如灰度图像)转换为灰度显示,而不能将多通道图像(如彩色图像)转换为灰度显示。如果您想将彩色图像转换为灰度图像并显示,可以使用 rgb2gray 函数将彩色图像转换为灰度图像,然后使用 plt.imshow 来显示灰度图像。

附上最终代码:

加入了坐标轴变换和关闭

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

file = 'lenargb.bmp'
pic = cv.imread(file)

pic = cv.cvtColor(pic, cv.COLOR_RGB2BGR)
cv.imshow('image', pic)
cv.waitKey(0)
cv.destroyAllWindows()
# 生成一个长宽和原图像一样的全黑图    
mask = np.zeros(pic.shape[:2],np.uint8) 
#print(mask.shape) #(512,512)
# 把感兴趣的地方变白
mask[200:300,200:300] = 255 # plt.imshow(pic)出来有坐标,可以找感兴趣的区域。但是纵轴上方为0,想要改成正常的坐标系的话:plt.imshow(pic,extent=(0, width, 0, height)) width和height用cv2的shape求
#show_pic('mask',mask)
# 与操作
masked_pic = cv.bitwise_and(pic,pic,mask=mask) 
#show_pic('masked_pic',masked_pic)
# 看原图和掩码过后的图的直方图
hist_full = cv.calcHist([pic],[0],None,[256],[0,256])
hist_mask = cv.calcHist([pic],[0],mask,[256],[0,256])

masked_pic = np.clip(masked_pic, 0, 255).astype('uint8')
# pic = pic.astype('uint8')

#masked_pic = np.clip(masked_pic, 0, 255).astype('uint8')

width = pic.shape[0] # 注意是方括号呀
height = pic.shape[1]
# cmap='gray'参数只能将单通道图像(如灰度图像)转换为灰度显示,而不能将多通道图像(如彩色图像)转换为灰度显示。
plt.subplot(221),plt.imshow(pic,extent=(0, width, 0, height),cmap='gray') #在这改成正常坐标系了
plt.subplot(222),plt.imshow(mask,cmap='gray'),plt.axis('off') # 关闭坐标轴
plt.subplot(223),plt.imshow(masked_pic,cmap='gray')
plt.subplot(224),plt.plot(hist_full),plt.plot(hist_mask)
plt.show()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值