发现两个问题
在昨天做实验的内容时,图像部分显示很奇怪,该亮的地方是黑色的(使用np.uint8后溢出导致的),以及不该亮的画面,出现过分亮的样子(矩阵中元素是浮点数导致的)
该亮的地方是黑色的
出现过分亮的样子
dtype = float
其实不仅是定义了类型,在进行矩阵运算的过程中,数值也很容易变成浮点数,如果没有对图像数据定义为uint8,会出现整个画面过白的情况,详情见cv.imshow使用手册内容:
红圈部分说明了,如果数据是浮点数,cv.imshow会把数值×255,因为他默认你的浮点数位于0~1之间,×255后,就可以在0到255之间了。
但是如果我们的数据是大于1的呢?是20呢?也会×255,这样那个位置的灰度值必大于255,所以会显示成白色。
小小测验,定义四个区域,灰度值分别为0.0, 0.3,1.01, 15。对于前两个浮点数,×255后,仍在可显示范围内,对于1.01×255>255,应该显示白色,15.0×255>255,应该显示白色。实验验证如下:
解决办法就是,在定义图像时,把他的类型定义成np.uint8型,如下:
img = np.ones([500, 500, 1], dtype=np.uint8)
但是uint8型也有其问题,下面继续说。
dtype = np.uint8
今早看到大佬总结的np.uint8
其实把我想表达的都说了,np.uint8会把高位部分砍掉,意思就是,比如图像进行矩阵运算后,得到某点的灰度值为260,那他实际存储值为:260 - 256 = 4,以为他会是白色的,事实上显示出来是黑色的。
验证如下:定义四个区域,灰度值分别为
从实际输出也可以看出来,并没有按照想象中的白色输出,而是显示成了黑色。
上面链接里,大佬也给出了他的解决办法:
cv2.normalize(img, out, 0, 255, cv2.NORM_MINMAX)
np.array([out],dtype=‘uint8’)
这样是可以的,先对数据处理后,再改变数据类型,同样的,可以使用:
np.clip(a, a_min, a_max)
np.array([out],dtype=‘uint8’)
也可以实现相应的效果,基于能力有限,目前没想到其他解决的好办法。
np.ones定义图像
最后,关于np.ones定义图像时,如果没有定义类型,他默认输出的是浮点数型,浮点数型可能就会导致我上述说的错误,需要注意下。
>>> a = np.ones([2,2,1])
>>> print(a)
[[[1.]
[1.]]
[[1.]
[1.]]]
定义类型后:
b = np.ones([2,2,1], dtype = np.uint8)
>>> print (b)
[[[1]
[1]]
[[1]
[1]]]
>>>
补充更新(2020.11.16)
今天做图像减法的时候遇到的,当时就想了一下,如果减出负数的话,uint8会怎么样?(因为uint8是无符号的嘛,只能存储0~255),测验了一下,负数的话,输入-1,输出255,输入-255,输出1。
那么如果:
输入-N,(-256<N<0)
输出的值是256-N。
输入-N,(N<-256)
先把输入加上256的倍数,加到(-256,0)这个范围内,再带进上式
OK!
本文是本人小总结,有不足的地方欢迎批评指正!