[bug] numpy.astype(uint8)和opencv imwrite函数的自动数据转换

时间:2021-02-17 16:08:26
现象描述 我在实现图像去模糊功能的时候,利用维纳滤波方法,因为对图像进行数字处理之后,其中数据格式变成了float32,其中有一些像素的值小于0或大于255,这个时候我利用numpy中的astype(uint8)进行类型转换,然后保存图片,结果如下图的右侧子图所示,出现了原则上不应该出现的红色边缘,这主要是由于红色通道图像出现了不再[0,255]区间的像素值,而这个时候我如果用astype(uint8)进行处理的话,数据就会出现截断或溢出,具体见图2实验。 [bug] numpy.astype(uint8)和opencv imwrite函数的自动数据转换 [bug] numpy.astype(uint8)和opencv imwrite函数的自动数据转换
[bug] numpy.astype(uint8)和opencv imwrite函数的自动数据转换             直接保存结果                                                       先转换数据astype()                                                                                        图1 [bug] numpy.astype(uint8)和opencv imwrite函数的自动数据转换
[bug] numpy.astype(uint8)和opencv imwrite函数的自动数据转换
图2
OpenCV 中imwrite函数对数据类型进行自动转换时,是根据如下的方法进行的:

   Saturation Arithmetics

As a computer vision library, OpenCV deals a lot with image pixels that are often encoded in a compact, 8- or 16-bit per channel, form and thus have a limited value range. Furthermore, certain operations on images, like color space conversions, brightness/contrast adjustments, sharpening, complex interpolation (bi-cubic, Lanczos) can produce values out of the available range. If you just store the lowest 8 (16) bits of the result, this results in visual artifacts and may affect a further image analysis. To solve this problem, the so-calledsaturation arithmetics is used. For example, to store r, the result of an operation, to an 8-bit image, you find the nearest value within the 0..255 range:

[bug] numpy.astype(uint8)和opencv imwrite函数的自动数据转换

Similar rules are applied to 8-bit signed, 16-bit signed and unsigned types. This semantics is used everywhere in the library. In C++ code, it is done using the saturate_cast<> functions that resemble standard C++ cast operations. See below the implementation of the formula provided above:

I.at<uchar>(y, x) = saturate_cast<uchar>(r);

wherecv::uchar is an OpenCV 8-bit unsigned integer type. In the optimized SIMD code, such SSE2 instructions aspaddusb,packuswb, and so on are used. They help achieve exactly the same behavior as in C++ code.

Note:


Saturation is not applied when the result is 32-bit integer.