有关函数cv2.imshow()处理不同图像深度时的数据转化问题

结论

当cv2.imshow()处理图像深度为CV_8U(默认范围为[0,255])时,按原数据显示;当处理图像深度为CV_16U(默认范围为[0,65535])时,除以256,映射到[0,255];当图像深度为CV_32F和CV_64F时(默认范围为[0,1]),乘以255映射到[0,255];当碰到负数时,首先取其绝对值,然后按照上述图像深度将超出数据范围的部分采取截断操作,最后映射到[0,255]显示图像

注:1. 图像深度为CV_32S在最新版本openCV4.1.0中已经无法显示

       2. openCV中处理数据溢出采用饱和操作,numpy处理数据溢出采用求模操作

我们先来简单介绍一下函数cv2.imshow()。

cv2.imshow(winname,mat)

概要

在一个指定窗口上显示图像

参数

  • winname:指定窗口的名字
  • mat:要显示的图像

通过以下代码可以先看看官方文件中有关数据类型转化的说明:

import cv2
help(cv2.imshow)

截取其中部分如下:

If the image is 8-bit unsigned, it is displayed as is.
If the image is 16-bit unsigned or 32-bit integer, the pixels are divided by 256. That is, the value range [0,255\*256] is mapped to [0,255].
If the image is 32-bit or 64-bit floating-point, the pixel values are multiplied by 255. That is, the value range [0,1] is mapped to [0,255].

翻译过来就是,如果图像数据类型为8位无符号整数,即范围[0,255],则按原有数据显示;如果数据类型为16位无符号整数或者32位有符号整数,则将数据除以256,映射到[0,255];如果数据类型为32位或64位浮点数,则将数据乘以255,映射到[0,255]。

但太过笼统,下面我们通过实例来一步步验证:

1. 图像深度为CV_8U,或者numpy数据类型为uint8

import numpy as np
import cv2
#新建numpy数组,注意np.zero()创建的数据类型为float64,所以先转化为uint8
img=np.zeros((500,500,3)).astype('uint8') 
#openCV显示图像为BGR格式,通过下列方式,我们绘制两条粗红线
img[150:170,150:350]=[0,0,100]
img[350:370,150:350]=[0,0,255] 
cv2.imshow('img',img)
cv2.waitKey() 
cv2.destroyAllWindows()

结果如下,可以看出当图像深度为CV_8U时,cv2.imshow()按原有数据显示,表现为明暗不同的两条红线,数字越大,亮度越大

2. 图像深度为CV_16U,或者numpy数据类型为uint16

import numpy as np
import cv2
#新建numpy数组,注意np.zero()创建的数据类型为float64,这里转化为uint16
img=np.zeros((500,500,3)).astype('uint16') 
#openCV显示图像为BGR格式,通过下列方式,我们绘制两条粗红线
img[150:170,150:350]=[0,0,1000]
img[350:370,150:350]=[0,0,65525] 
cv2.imshow('img',img)
cv2.waitKey() 
cv2.destroyAllWindows()

结果如下,可以看到,当数据类型为uint16,由于cv2.imshow()处理数据时要将图像矩阵先除以256,所以当原数据大小为1000时,亮度很小,几乎看不到。

3. 图像深度为CV_32S,或者numpy数据类型为int32

import numpy as np
import cv2
#新建numpy数组,注意np.zero()创建的数据类型为float64,这里转化为int32
img=np.zeros((500,500,3)).astype('int32') 
#openCV显示图像为BGR格式,通过下列方式,我们绘制两条粗红线
img[150:170,150:350]=[0,0,1000]
img[350:370,150:350]=[0,0,65525] 
cv2.imshow('img',img)
cv2.waitKey() 
cv2.destroyAllWindows()

运行结果报错,个人理解可能是openCV4.1.0版本中函数cv2.imshow()的显示图像不再支持CV_32S的图像深度

4. 图像深度为CV_32F、CV_64F,或者numpy数据类型为float32、float64

import numpy as np
import cv2
#新建numpy数组,注意np.zero()创建的数据类型为float64
img=np.zeros((500,500,3))
#openCV显示图像为BGR格式,通过下列方式,我们绘制三条粗红线
img[150:170,150:350]=[0,0,-8000]
img[250:270,150:350]=[0,0,8000]
img[350:370,150:350]=[0,0,0.34]
cv2.imshow('img',img)
cv2.waitKey() 
cv2.destroyAllWindows()

结果如下:

当图像深度为CV_32F,CV_64F时,数据大小默认的范围为[0,1](注:这一点有别于numpy数组)。从图像中可以看出cv2.imshow()在处理负数时首先将其转化为正数,而后采用截断操作(即大于1的数保留为1,其余不变)。数据值为1最明亮;数据值为0,最暗。

发布了29 篇原创文章 · 获赞 26 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_42216109/article/details/89707220