OpenCV里imshow()处理不同数据类型的numpy.ndarray分析 您所在的位置:网站首页 region复数 OpenCV里imshow()处理不同数据类型的numpy.ndarray分析

OpenCV里imshow()处理不同数据类型的numpy.ndarray分析

2023-08-21 09:34| 来源: 网络整理| 查看: 265

文章目录 测试不同数据类型uint8uint16int32float32和float64 实际使用注意总结

Python 3.6opencv-python==3.4.2.16numpy==1.16.2

针对不同数据类型的numpy.ndarray,cv2.imshow()处理结果不同。 本文就此进行试验,新建不同类型的numpy.ndarray,使用cv2.imshow()显示结果分析。

使用pycharm按住Ctrl加鼠标左键进入函数cv2.imshow()可以看见文档

The function imshow displays an image in the specified window. If the window was created with the . cv::WINDOW_AUTOSIZE flag, the image is shown with its original size, however it is still limited by the screen resolution. . Otherwise, the image is scaled to fit the window. The function may scale the image, depending on its depth: . . - 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].

机翻:

imshow函数在指定窗口中显示图像。如果窗口是用WINDOW_AUTOSIZE标志,图像以其原始大小显示,但仍受屏幕分辨率的限制。 否则,将缩放图像以适应窗口。该函数可根据图像的深度缩放图像: 如果图像是8位无符号的,则按原样显示。 如果图像是16位无符号或32位整数,则像素除以256。也就是说值范围[0, 255*256]映射到[0, 255]。 如果图像是32位或64位浮点,则像素值乘以255。也就是说值范围[0, 1]映射到[0, 255]。

写demo演示

测试不同数据类型 uint8 import cv2 import numpy as np height, width = 200, 200 def test_uint8(): img_a = np.zeros((height, width, 3), dtype='uint8') img_a[:, :, 0] = 255 print(f'img_a[0, 0, 0]={img_a[0, 0, 0]}\n' f'type(img_a)={type(img_a)}\nimg_a.dtype={img_a.dtype}\nimg_a.shape={img_a.shape}\n') ''' img_a[0, 0, 0]=255 type(img_a)= img_a.dtype=uint8 img_a.shape=(200, 200, 3) ''' img_b = np.zeros((height, width, 3), dtype='uint8') img_b[:, :, 0] = 0.8 print(f'img_b[0, 0, 0]={img_b[0, 0, 0]}\n' f'type(img_b)={type(img_b)}\nimg_b.dtype={img_b.dtype}\nimg_b.shape={img_b.shape}\n') ''' img_b[0, 0, 0]=0 type(img_b)= img_b.dtype=uint8 img_b.shape=(200, 200, 3) ''' img_c = np.zeros((height, width, 3), dtype='uint8') img_c[:, :, 0] = 300 print(f'img_c[0, 0, 0]={img_c[0, 0, 0]}\n' f'type(img_c)={type(img_c)}\nimg_c.dtype={img_c.dtype}\nimg_c.shape={img_c.shape}\n') ''' img_c[0, 0, 0]=44 type(img_c)= img_c.dtype=uint8 img_c.shape=(200, 200, 3) ''' img_d = np.zeros((height, width, 3)) img_d[:, :, 0] = 256 print(f'img_d[0, 0, 0]={img_d[0, 0, 0]}\n' f'type(img_d)={type(img_d)}\nimg_d.dtype={img_d.dtype}\nimg_d.shape={img_d.shape}\n') # 对其进行类型转换 img_d = img_d.astype('uint8') print(f'img_d[0, 0, 0]={img_d[0, 0, 0]}\n' f'type(img_d)={type(img_d)}\nimg_d.dtype={img_d.dtype}\nimg_d.shape={img_d.shape}\n') ''' img_d[0, 0, 0]=256.0 type(img_d)= img_d.dtype=float64 img_d.shape=(200, 200, 3) img_d[0, 0, 0]=0 type(img_d)= img_d.dtype=uint8 img_d.shape=(200, 200, 3) ''' cv2.imshow('a', img_a) cv2.imshow('b', img_b) cv2.imshow('c', img_c) cv2.imshow('d', img_d) cv2.waitKey(0) cv2.destroyAllWindows()

显示图片为 在这里插入图片描述 uint8为无符号8位整型,uint8范围为0 ~ 2 8 − 1 2^8-1 28−1,即0~255。 将所有像素值类型都转换为uint8类型,imshow()再按原样显示。转换规则为

若为浮点型,直接去除小数部分再将整数n按照取模运算n%256映射到0~255 import numpy as np arr = np.array([-1.8, -1.3, -256.5, 100.3, 100.7]) print(f'arr.dtype={arr.dtype},\tarr={arr}') # arr.dtype=float64, arr=[ -1.8 -1.3 -256.5 100.3 100.7] arr = arr.astype('uint8') print(f'arr.dtype={arr.dtype},\tarr={arr}') # arr.dtype=uint8, arr=[255 255 0 100 100] uint16 def test_uint16(): img_a = np.zeros((height, width, 3), dtype='uint16') img_a[:, :, 2] = 255 print(f'img_a[0, 0, 2]={img_a[0, 0, 2]}\n' f'type(img_a)={type(img_a)}\nimg_a.dtype={img_a.dtype}\n') cv2.imshow('a', img_a) ''' img_a[0, 0, 2]=255 type(img_a)= img_a.dtype=uint16 ''' img_a[:, :, 2] = 255 * 256 print(f'img_a[0, 0, 2]={img_a[0, 0, 2]}\n' f'type(img_a)={type(img_a)}\nimg_a.dtype={img_a.dtype}\n') cv2.imshow('b', img_a) ''' img_a[0, 0, 2]=65280 type(img_a)= img_a.dtype=uint16 ''' img_a[:, :, 2] = 255 * 256 + 257 print(f'img_a[0, 0, 2]={img_a[0, 0, 2]}\n' f'type(img_a)={type(img_a)}\nimg_a.dtype={img_a.dtype}\n') cv2.imshow('c', img_a) ''' img_a[0, 0, 2]=1 type(img_a)= img_a.dtype=uint16 ''' img_a[:, :, 2] = 255 * 256 + 200 print(f'img_a[0, 0, 2]={img_a[0, 0, 2]}\n' f'type(img_a)={type(img_a)}\nimg_a.dtype={img_a.dtype}\n') cv2.imshow('d', img_a) ''' img_a[0, 0, 2]=65480 type(img_a)= img_a.dtype=uint16 ''' cv2.waitKey(0) cv2.destroyAllWindows()

显示如图 在这里插入图片描述 uint16为无符号16位整型,uint16范围为0 ~ 2 16 − 1 2^{16}-1 216−1,即0~65535。

将所有像素值类型都转换为uint16类型。 转换规则同uint8类型转换类似,首先除去小数部分;再模65536。imshow()将uint16类型像素除以256再显示。 由实验猜测对于uint16类型像素值在范围0~255*256的除以256显示,对于超出范围的像素,去除超出部分按最小或最大值计算。 int32 def test_int32(): img_a = np.zeros((height, width, 3), dtype='int32') img_a[:, :, 1] = 255 print(f'img_a[0, 0, 1]={img_a[0, 0, 1]}\n' f'type(img_a)={type(img_a)}\nimg_a.dtype={img_a.dtype}\n') ''' img_a[0, 0, 1]=255 type(img_a)= img_a.dtype=int32 ''' cv2.imshow('a', img_a) img_a[:, :, 1] = 255 * 256 print(f'img_a[0, 0, 1]={img_a[0, 0, 1]}\n' f'type(img_a)={type(img_a)}\nimg_a.dtype={img_a.dtype}\n') ''' img_a[0, 0, 1]=65280 type(img_a)= img_a.dtype=int32 ''' cv2.imshow('b', img_a) img_a[:, :, 1] = 3 * 255 * 256 print(f'img_a[0, 0, 1]={img_a[0, 0, 1]}\n' f'type(img_a)={type(img_a)}\nimg_a.dtype={img_a.dtype}\n') ''' img_a[0, 0, 1]=195840 type(img_a)= img_a.dtype=int32 ''' cv2.imshow('c', img_a) img_a[:, :, 1] = -255 * 256 print(f'img_a[0, 0, 1]={img_a[0, 0, 1]}\n' f'type(img_a)={type(img_a)}\nimg_a.dtype={img_a.dtype}\n') ''' img_a[0, 0, 1]=-65280 type(img_a)= img_a.dtype=int32 ''' cv2.imshow('d', img_a) cv2.waitKey(0) cv2.destroyAllWindows()

显示图片如下 在这里插入图片描述 int32为有符号32位整型,范围为 − 2 31 ∼ 2 31 − 1 -2^{31} \sim 2^{31}-1 −231∼231−1 。 同uint16一样,首先将像素值类型转换为int32类型;其次imshow()将像素值除以256显示 由实验猜测对于int32类型像素值在范围0~255x256的除以256显示,对于超出范围的去除超出部分按最小或最大值计算。 − 2 31 ∼ 0 -2^{31} \sim 0 −231∼0 按0计算, 255 × 256 + 1 ∼ 2 31 − 1 255 \times 256+1\sim2^{31}-1 255×256+1∼231−1按255*256计算。

float32和float64

这里以float32为例,float64类似

def test_float32(): img_a = np.zeros((height, width, 3), dtype='float32') img_a[:, :, 0] = 255 print(f'img_a[0, 0, 0]={img_a[0, 0, 0]}\n' f'type(img_a)={type(img_a)}\nimg_a.dtype={img_a.dtype}\n') ''' img_a[0, 0, 0]=255.0 type(img_a)= img_a.dtype=float32 ''' cv2.imshow('a', img_a) img_a[:, :, 0] = 1 print(f'img_a[0, 0, 0]={img_a[0, 0, 0]}\n' f'type(img_a)={type(img_a)}\nimg_a.dtype={img_a.dtype}\n') ''' img_a[0, 0, 0]=1.0 type(img_a)= img_a.dtype=float32 ''' cv2.imshow('b', img_a) img_a[:, :, 0] = 0.5 print(f'img_a[0, 0, 0]={img_a[0, 0, 0]}\n' f'type(img_a)={type(img_a)}\nimg_a.dtype={img_a.dtype}\n') ''' img_a[0, 0, 0]=0.5 type(img_a)= img_a.dtype=float32 ''' cv2.imshow('c', img_a) img_a[:, :, 0] = -0.8 print(f'img_a[0, 0, 0]={img_a[0, 0, 0]}\n' f'type(img_a)={type(img_a)}\nimg_a.dtype={img_a.dtype}\n') ''' img_a[0, 0, 0]=-0.800000011920929 type(img_a)= img_a.dtype=float32 ''' cv2.imshow('d', img_a) cv2.waitKey(0) cv2.destroyAllWindows()

显示如图 在这里插入图片描述 float32是浮点型,imshow()是将0 ~ 1范围像素值乘以255,映射为0 ~ 255显示。 由实验猜测对于0~1以外的像素值,作截断处理,分别取对应的边界,然后再乘以255显示。

实际使用注意

根据实际使用中的经验,需要注意的地方有: 针对图像,如果是进行归一化后的float32或者float64类型numpy.ndarray,则像素值范围在0~1内,用cv2.imshow()可以正常显示。 但如果进行类型转换为uint8,再用cv2.imshow()显示,则为全黑,无法正常显示;如果转换为uint16或int32,则显示也是全黑。

def float32_else(): img = np.zeros((200, 300, 3), dtype='float32') img[:, :, 2] = 1.0 print(f'img.dtype={img.dtype}, img[0,0,2]={img[0,0,2]}') cv2.imshow('float32', img) img = img.astype('uint8') print(f'img.dtype={img.dtype}, img[0,0,2]={img[0,0,2]}') cv2.imshow('uint8', img) img = img.astype('uint16') print(f'img.dtype={img.dtype}, img[0,0,2]={img[0,0,2]}') cv2.imshow('uint16', img) img = img.astype('int32') print(f'img.dtype={img.dtype}, img[0,0,2]={img[0,0,2]}') cv2.imshow('int32', img) cv2.waitKey(0) cv2.destroyAllWindows() ''' img.dtype=float32, img[0,0,2]=1.0 img.dtype=uint8, img[0,0,2]=1 img.dtype=uint16, img[0,0,2]=1 img.dtype=int32, img[0,0,2]=1 '''

显示图片为 在这里插入图片描述 同样,其他的数据类型转换,用cv2.imshow()也可能会出现问题,这里就不再一一演示了,感兴趣的同学可以自己尝试下。 但只要熟知针对不同数据类型的numpy.ndarray,cv2.imshow()的不同处理方式,就可以弄懂其中原因,并进行修改。

总结 首先得将图像像素值类型,强制转换为对应的数据类型。imshow()再根据不同类型进行不同操作后,显示出来。 如果图像是8位无符号的,则按原样显示。 如果图像是16位无符号或32位整数,则像素除以256。也就是说值范围[0, 255x256]映射到[0, 255]。 如果图像是32位或64位浮点,则像素值乘以255。也就是说值范围[0, 1]映射到[0, 255]。 根据实验猜测:对于超出映射范围的像素值,截断按其边界处理,再按规则映射,这里欢迎大家讨论交流,互相学习。


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有