[bug] numpy.astype(uint8)和opencv imwrite函式的自動資料轉換

LinJM-機器視覺發表於2016-04-07
現象描述
我在實現影象去模糊功能的時候,利用維納濾波方法,因為對影象進行數字處理之後,其中資料格式變成了float32,其中有一些畫素的值小於0或大於255,這個時候我利用numpy中的astype(uint8)進行型別轉換,然後儲存圖片,結果如下圖的右側子圖所示,出現了原則上不應該出現的紅色邊緣,這主要是由於紅色通道影象出現了不再[0,255]區間的畫素值,而這個時候我如果用astype(uint8)進行處理的話,資料就會出現截斷或溢位,具體見圖2實驗。
 
            直接儲存結果                                                       先轉換資料astype()
                                                                                       圖1


圖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-called saturation 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:

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);

where cv::uchar is an OpenCV 8-bit unsigned integer type. In the optimized SIMD code, such SSE2 instructions as paddusb, 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.




相關文章