matplotlib与opencv图像读取与显示的问题

个人博客 :Sekyoro的博客小屋
个人网站 :Proanimer的个人网站

最近在用opencv和matplotlib展示图片,但是遇到了一些问题,这里展开说说

首先需要明确的是,opencv和matplotlib读取图片都是通道在最后,而前者默认可见光图像是BGR,后者是RGB.此外还有PIL以及imageio等读取图像的工具,这里不一一赘述.

Opencv

对于opencv,使用cv2.imshow,cv2.imread以及cv2.imwrite来读写以及显示.

imshow

显示图像的缩放取决于图像深度:

对 8 位无符号图像,按原样显示;

对 16 位无符号或 32 位整数图像,将像素值范围 [0,255*255] 映射到 [0,255] 显示;

对 32 位浮点图像,将像素值范围 [0,1] 映射到 [0,255] 显示;

当cv2.imshow()处理图像深度为CV_8U(默认范围为[0,255])时,按原数据显示;

当处理图像深度为CV_16U(默认范围为[0,65535])时,除以256,映射到[0,255];

当图像深度为CV_32F和CV_64F时(默认范围为[0,1]),乘以255映射到[0,255],超过255直接饱和;

当输入负数时,当作0来处理

python 复制代码
import numpy as np
import cv2

img = np.zeros((500, 500, 1))
print(img.dtype)
img[150:170, 150:350] = 10
img[250:270, 150:350] = -1
img[350:370, 150:350] = -10
print(img[350:170, 150:350])
cv2.imshow('img', img)
cv2.waitKey()

由于numpy默认类型float64,浮点数会乘以255,所以只有最上面有一条白线.负值直接黑色

python 复制代码
import numpy as np
import cv2
# 新建numpy数组,注意np.zero()创建的数据类型为float64
img = np.zeros((500, 500, 1))
print(img.dtype)
img[150:170, 150:350] = 10
img[250:270, 150:350] = 255
img[350:370, 150:350] = 1
print(img[350:170, 150:350])
cv2.imshow('img', img)
cv2.waitKey()

而如果是大于1的浮点数,也是直接饱和.

如果是uint8,如果超出255,则会被numpy截取,也就是取模

python 复制代码
img = np.zeros((500, 500, 1),dtype=np.uint8)
print(img.dtype)
img[150:170, 150:350] = 10
img[250:270, 150:350] = 20
img[350:370, 150:350] = 30
cv2.imshow('img', img)
print(img[350:370, 150:350])
cv2.waitKey()
python 复制代码
img = np.zeros((500, 500, 1),dtype=np.uint8)
print(img.dtype)
img[150:170, 150:350] = 10
img[250:270, 150:350] =  512
img[350:370, 150:350] = 255
cv2.imshow('img', img)
print(img[250:270, 150:350])
cv2.waitKey()

打印img[250:270, 150:350]的值发现是0

python 复制代码
img = np.zeros((500, 500, 1))
print(img.dtype)
img[150:170, 150:350] = 10
img[250:270, 150:350] =  512
img[350:370, 150:350] = 255
cv2.imshow('img', img)
print(img[250:270, 150:350])
cv2.waitKey()

所以这涉及两个问题,一个是本身numpy的截取另一个是opencv的截取机制.

python 复制代码
img = np.zeros((500, 500, 1), dtype=np.uint16)
print(img.dtype)
img[150:170, 150:350] = 2
img[250:270, 150:350] = 255*255
img[350:370, 150:350] = 255*100
cv2.imshow('img', img)
cv2.waitKey(0)
print(img[250:270, 150:350])
cv2.imwrite("test.png", img)

如果是16位无符号整数,会除以255.

最后注意,如果是int32可能会报错

imwrite

机制与imshow类似,不过会根据保存文件的后缀进行编码参数.

cv2.imwrite() 能保存 BGR 3通道图像,或 8 位单通道图像、或 PNG/JPEG/TIFF 16位无符号单通道图像

注意:如果保存float32的图像值超过了1,此时会与imshow机制不同,表现为值被归到0-255

python 复制代码
a = np.ones([255,255,1],dtype=np.float32)
a[0:255,0:255] = 10
print(a)
cv2.imshow("img",a)
cv2.waitKey()
cv2.imwrite("test.png",a)

上面有两张图,分别是imwrite的图片与imshow的图片,由于是浮点数,imshow展示时乘了255导致饱和白色.所以会说imwrite对浮点数不友好,不符合imshow的道理,

imread

注意如果有通道则通道在最后,可以设置

IMREAD_UNCHANGED = -1, //如果设置,则返回的数据带有alpha通道(R,G,B,A 四个通道),否则没有alpha通道

IMREAD_GRAYSCALE = 0, //如果设置,则将图像转换为单通道灰度图像

IMREAD_COLOR = 1, //如果设置,则将图像转换成3通道BGR彩色图像

IMREAD_ANYDEPTH = 2, //如果设置,则在输入具有相应深度时返回16位/32位图像,否则将其转换为8位

IMREAD_ANYCOLOR = 4, //如果设置,则图像可能以任何颜色格式读取

IMREAD_LOAD_GDAL = 8, //如果设置,使用gdal驱动程序加载图像

IMREAD_REDUCED_GRAYSCALE_2 = 16, //如果设置,总是将图像转换为单通道灰度图像且图像大小减少1/2

IMREAD_REDUCED_COLOR_2 = 17, //如果设置,总是将图像转换为3通道BGR彩色图像且图像大小减少1/2

IMREAD_REDUCED_GRAYSCALE_4 = 32, //如果设置,总是将图像转换为单通道灰度图像且图像大小减少1/4

IMREAD_REDUCED_COLOR_4 = 33, //如果设置,总是将图像转换为3通道BGR彩色图像且图像大小减少1/4

IMREAD_REDUCED_GRAYSCALE_8 = 64, //如果设置,总是将图像转换为单通道灰度图像且图像大小减少1/8

IMREAD_REDUCED_COLOR_8 = 65, //如果设置,总是将图像转换为3通道BGR彩色图像且图像大小减少1/8

IMREAD_IGNORE_ORIENTATION = 128 //如果设置,不会根据EXIF的方向标志旋转图像

Matplotlib

imshow

主要讲讲matplotlib的imshow

matplotlib在imshow时,如果接收到的是二维矩阵,会自动归一化,映射到彩色。如果输入的矩阵里面值都是一样的,归一化会把他们全部变为255,也就是呈现黑色。

用于在使用 cmap 映射到颜色之前将标量数据缩放到 [0, 1] 范围的归一化方法。默认情况下,使用线性缩放,将最低值映射到 0,将最高值映射到 1。

imshow的输入

图像数据。支持的数组形状有:(M,N):具有标量数据的图像。使用归一化和颜色图将值映射到颜色。请参阅参数norm、cmap、vmin、vmax。

(M, N, 3):具有 RGB 值(0-1 float 或 0-255 int)的图像。

(M, N, 4):具有 RGBA 值(0-1 float 或 0-255 int)的图像,即包括透明度。前两个维度(M、N)定义图像的行和列。超出范围的 RGB(A) 值将被剪裁。

所以如果使用单通道的数据,会默认norm,而这种norm是根据输入值的min-max进行norm,并不是norm到0-255

python 复制代码
img = torch.ones(152,152,1,dtype=torch.uint8)*220
img = img.numpy()
plt.imshow(img,cmap="gray")
plt.show()

解决办法是设置vmin=0,vmax=255,当然使用三通道也可以

相关问题

  1. matplotlib 可视化图像明明255,结果出来全为黑色的问题_plt.imshow 不加vmin和vmax参数是全黑的_佳hong的博客-CSDN博客
  2. 有关函数cv2.imshow()处理不同图像深度时的数据转化问题_cv2.cv_8u图像深度-CSDN博客这篇文章有点问题,目前opencv将负值作为0处理
  3. opencv中imwrite对float的处理 - siren27 - 博客园 (cnblogs.com)
  4. 【精选】使用 tiff/png 文件类型对 uint16_t/float 数据类型存取的无聊实验_float存储方式和uint16-CSDN博客

如有疑问,欢迎各位交流!

服务器配置

宝塔:宝塔服务器面板,一键全能部署及管理

云服务器:阿里云服务器
Vultr服务器

GPU服务器:Vast.ai

相关推荐
AI营销干货站5 分钟前
2025 AI市场舆情分析软件测评:原圈科技等3款工具深度对比
大数据·人工智能
微爱帮监所写信寄信6 分钟前
微爱帮监狱寄信写信系统后台PHP框架优化实战手册
android·开发语言·人工智能·网络协议·微信·https·php
民乐团扒谱机10 分钟前
【微实验】量子光梳技术革命:如何用量子压缩突破时频传递的终极极限?
人工智能·敏感性分析·量子力学·双梳
MARS_AI_12 分钟前
AI呼叫中心革命:大模型技术如何重构企业服务体验
人工智能·科技·自然语言处理·信息与通信·agi
EEPI20 分钟前
【论文阅读】Vision Language Models are In-Context Value Learners
论文阅读·人工智能·语言模型
金融Tech趋势派21 分钟前
2026企业微信私有化部署新选择:微盛·企微管家如何助力企业数据安全与运营效率提升?
大数据·人工智能·云计算·企业微信
短视频矩阵源码定制22 分钟前
专业的矩阵系统哪个公司好
大数据·人工智能·矩阵
jimmyleeee23 分钟前
人工智能基础知识笔记三十:模型的混合量化策略
人工智能·笔记
Gofarlic_oms125 分钟前
Cadence许可证全生命周期数据治理方案
java·大数据·运维·开发语言·人工智能·安全·自动化
Nautiluss34 分钟前
一起调试XVF3800麦克风阵列(三)
linux·人工智能·嵌入式硬件·音频·语音识别·dsp开发·智能音箱