In OpenCV, if the image is of floating point type, then only those pixels can be visualized using imshow
, which have value from 0.0 to 1.0, if the value is greater than 1.0, it will be shown as a white pixel and if less than 0.0, it will be shown as black pixel.
To visualize a floating point image, scale its values to the range 0.0 - 1.0
.
As for the conversion part.... When used with default arguments, the cv::Mat::convertTo
function just creates a matrix of the specified type, and then copies the values from the source matrix and then rounds them to the nearest possible value of the destination data type.
If the value is out of range, it is clamped to the minimum or maximum values.
In the documentation of imshow
, it is written that:
If the image is 32-bit floating-point, the pixel values are multiplied
by 255. That is, the value range [0,1] is mapped to [0,255].
It means that only the values in the range 0.0 to 1.0 will be mapped to 0 to 255. If a value is greater than 1.0, and multiplied by 255, it will become greater than 255. Then it will be clamped to the range of CV_8U
and eventually it will also become 255.
In your example, all the values which are 1000, will become 255 in the destination matrix as the destination type is CV_8U
and the maximum possible value is 255. All the floating point values will be floor
ed. No automatic mapping is done.
To appropriately map the values to the range of CV_8U
use the 3rd and 4th parameters of the function cv::Mat::convertTo
, so that the values are scaled before the conversion is done.
Suppose the matrix A
has minimum and maximum values Min
and Max
, where Min!=Max
.
To properly scale the values from 0 to 255, you can do the following:
if (Min!=Max){
A -= Min;
A.convertTo(B,CV_8U,255.0/(Max-Min));
}
You can also do this directly like this:
if (Min!=Max)
A.convertTo(B,CV_8U,255.0/(Max-Min),-255.0*Min/(Max-Min));
(edited taking into account zhangxaochen's comment)