从图像读取的Numpy数组元素平方结果异常(数值未超过原数组)的问题求助
从图像读取的Numpy数组元素平方结果异常(数值未超过原数组)的问题求助
看起来你遇到的是uint8数据类型溢出的典型问题,这可是OpenCV读图像时的常见坑!
问题根源
OpenCV的cv2.imread()默认会把图像读成uint8类型的Numpy数组——也就是8位无符号整数,取值范围被死死限制在0到255之间。当你对这种数组做平方运算时,Numpy不会自动帮你升级精度,而是直接把超出255的结果截断/取模到uint8的范围内:
- 比如原数组里的255,平方后是65025,转换成uint8就变成了
65025 % 256 = 97 - 而原数组里的53,平方后是2809,取模后是
2809 % 256 = 249
这就导致你看到平方后的最大值(249)反而比原数组最大值(255)还小——因为溢出后的数值是循环的,部分中间值的平方取模结果反而更大。
解决方案
解决起来很简单,只要先把数组转换成更高精度的类型(比如uint32、int64或者浮点型),再做平方运算就行。另外顺便提一句,你代码里的im22=im最好改成im22=im.copy(),不然im22会和原数组im共享内存,修改im22时原图像也会被改动,容易出意外。
修改后的代码如下:
import numpy as np import cv2 im = cv2.imread("blue") im22 = im.copy() # 改成copy避免修改原数组 im22[im22 < 100] = 0 blue = np.array(im22[:, :, 2]) # 关键步骤:转换为高精度类型 blue_high_precision = blue.astype(np.uint32) # 用float64也完全没问题 blue2 = np.square(blue_high_precision) print("type is ", type(blue)) print("blue max", np.max(blue)) print("blue min", np.min(blue)) print("blue Squared max", np.max(blue2)) print("blue Squared min", np.min(blue2))
为什么你用非图像数据集时没问题?因为手动创建的数组默认一般是int32或浮点类型,没有0-255的范围限制,平方结果自然能正常保留啦。
内容来源于stack exchange




