为什么在OpenCV Python包装中数据类型必须是'uint8'?

6 投票
4 回答
26572 浏览
提问于 2025-04-18 07:03

我想用以下代码创建一个灰色的图像:

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 个回答

1

如果你想要输出一张灰色的图片,可以试试下面的代码,这样就能得到你想要的结果。不错的尝试。

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

4

因为OpenCV读取图像时默认使用的类型是'uint8',所以对这个图像进行操作的所有东西也必须是'uint8'类型,这样才能兼容。

4

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}

8

根据文档,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

撰写回答