I am working with TIF images containing signed integer data. After successfully inputing one and processing it I need to output the image in the same format (input and output both *.tif files).
For the input, I know that OpenCV does not know if the data is signed or unsigned, so it assumes unsigned. Using this trick solves that problem (switching the type of cv::Mat
by hand).
However, when I output the image and load it again, I do not get the expected result. The file contains multiple segments (groups of pixels), and the format is as follows (I must use this format):
-9999
1
, second 2
etc)And here is the example code:
void ImageProcessor::saveSegments(const std::string &filename){
cv::Mat segmentation = cv::Mat(workingImage.size().height,
workingImage.size().width,
CV_32S, cv::Scalar(-9999));
for (int i=0, szi = segmentsInput.size(); i < szi; ++i){
for (int j=0, szj = segmentsInput[i].size(); j < szj; ++j){
segmentation.at<int>(segmentsInput[i][j].Y,
ssegmentsInput[i][j].X) = i+1;
}
}
cv::imwrite(filename, segmentation);
}
You can assume that all the variables (e.g. workingImage
, segmentsInput
) exist as global variables.
Using this code, when I input the image and examine the values, most of the values are set to 0
while the ones that are set take a full range of integer values (in my example I had 20 segments).
You can't save integer matrices directly with imwrite. As the documentation states: "Only 8-bit (or 16-bit unsigned (CV_16U) in case of PNG, JPEG 2000, and TIFF) single-channel or 3-channel (with ‘BGR’ channel order) images can be saved using this function."
However, what you could do it to convert your CV_32S
matrix to a CV_8UC4
and save it as a PNG with no compression. Of course, this is a bit unsafe since endianness comes into play and may change your values between different systems or compilers (especially since we're talking about signed integers here). If you use always the same system and compiler, you can use this:
cv::Mat segmentation = cv::Mat(workingImage.size().height,
workingImage.size().width,
CV_32S, cv::Scalar(-9999));
cv::Mat pngSegmentation(segmentation.rows, segmentation.cols, CV_8UC4, (cv::Vec4b*)segmentation.data);
std::vector<int> params;
params.push_back(CV_IMWRITE_PNG_COMPRESSION);
params.push_back(0);
cv::imwrite("segmentation.png", pngSegmentation, params);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With