为什么在OpenCV Python包装中数据类型必须是'uint8'?
我想用以下代码创建一个灰色的图像:
import numpy as np
import cv2
cv=cv2
s=np.zeros((240, 320, 3), dtype=int)
s[s==0]=128
cv.imshow('3', s)
cv.waitKey()
cv.destroyAllWindows()
但是我得到的图像完全是黑色。当我把图像写入文件时,它确实是灰色的:
fn='example.jpg'
cv.imwrite(fn, s)
所以我必须把int
改成uint8
,这样一切就正常了。不过我还是很好奇,为什么我必须使用uint8
而不是int
,有没有什么文档可以说明这个问题?
4 个回答
如果你想要输出一张灰色的图片,可以试试下面的代码,这样就能得到你想要的结果。不错的尝试。
import cv2 as cv import numpy as np img = cv.imread('C:/Users/Admin/Downloads/Opencv/tiger.png') #cv.imshow('tiger', img) #this code will shows you a normal image #cv.waitKey(0) #cv.destroyAllWindows() gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) cv.imshow('Gray', gray) #this above code will shows you a gray colour image cv.waitKey(0) cv.destroyAllWindows()
如果你想了解更多信息,可以查看颜色转换的相关文档 - https://docs.opencv.org/3.4/d8/d01/group__imgproc__color__conversions.html
因为OpenCV读取图像时默认使用的类型是'uint8',所以对这个图像进行操作的所有东西也必须是'uint8'类型,这样才能兼容。
uint8
是一种无符号的8位整数,可以表示从0到255的值。而 int
通常是一个32位的有符号整数。当你用 dtype=int
创建数组时,数组中的每个元素会占用4个字节。OpenCV 似乎希望数组由8位的元组组成,这些元组代表红色、绿色和蓝色。因此,当你传递一个整数数组时,内存中会包含类似这样的内容:
0x00000080 0x00000080 0x00000080.......
OpenCV 会将其解释为:
{R=0x00,G=0x00,B=0x00} {R=0x80,G=0x00,B=0x00}, {R=0x00, G=0x00, B=0x00}...
我猜这会导致你得到一幅非常暗的图像,仔细看会发现红、绿、蓝像素都很暗淡。
当你把类型改为 uint8
时,你的数组会变成这样:
0x80 0x80 0x80 0x80 0x80 0x80 0x80....
这时 OpenCV 会将其解释为灰色的 RGB 值:
{R=0x80,G=0x80,B=0x80}
根据文档,OpenCV会根据数组的类型来改变它的显示方式:
- 如果图像是8位无符号整数,它会直接显示出来。
- 如果图像是16位无符号整数或32位整数,像素值会被除以256。也就是说,值的范围[0,255*256]会被映射到[0,255]。
- 如果图像是32位浮点数,像素值会被乘以255。也就是说,值的范围[0,1]会被映射到[0,255]。
因此,下面的代码都会生成相同的灰度图像:
s = np.zeros((240, 320), dtype=np.uint8)
s[s==0] = 128
int32
:
s = np.zeros((240, 320), dtype=np.int32)
s[s==0] = 128 * 256
float32
:
s = np.zeros((240, 320), dtype=np.float32)
s[s==0] = 128 / 256.0