user2077721
user2077721

Reputation: 29

OpenCV : Convert a CV_8UC3 image to a CV_32S1 image in C++

I need to convert a CV_8U image with 3 channels to an image which must be a single channel CV_32S. But when I'm trying to do so, the image I get is all black. I don't understand why my code is not working.

I'm dealing with a grayscale image, this is why I split the 3 channels image into a vector of single channel image, and then process only the first channel.

//markers->Image() returns a valid image, so this is not the problem

cv::Mat dst(markers->Image().size(), CV_32SC1);
dst = cv::Scalar::all(0);
std::vector<cv::Mat> vectmp;
cv::split(markers->Image(), vectmp);
vectmp.at(0).convertTo(dst, CV_32S);

//vectmp.at(0) is ok, but dst is black...?

Thank you in advance.

Upvotes: 2

Views: 4572

Answers (4)

user2882399
user2882399

Reputation:

I believe this is what you are looking for. Convert your image to this, 8 bit, single channel. CV_8UC1. You are starting with a 8 bit image and changing it to 32 bit single channel? Why? Keep it 8 bit.

Upvotes: 0

Jyl
Jyl

Reputation: 1

I had the same problem, solved it indirectly by trying to convert a 8UC1 to 32S instead of 8UC3.

RgbToGray accept to create a gray image using 8UC3 or 8UC1 element type. 8UC1 image is my marker image.

I've done this in Opencvsharp :

Mat buf3 = new Mat(iplImageMarker);
buf3.ConvertTo(buf3, MatType.CV_32SC1);
iplImageMarker= (IplImage)buf3;

iplImageMarker=iplImageMarker* 256;

Upvotes: 0

mpenkov
mpenkov

Reputation: 21902

If you want to display your 32-bit image and see a meaningful result, you need to multiply all of its elements by 256 prior to calling imshow. Otherwise, imshow will scale your values down to zero and you will get a black image (as Astor has pointed out).

Since the original values are 8 bit unsigned, they must be less than 255. Therefore multiplying them by 256 is safe and will not overflow a 32-bit integer.

EDIT I just realized your output type is a signed 32-bit integer, but the original type is unsigned 8-bit integer. In that case, you need to scale your values appropriately (have a look at scaleAdd).

Finally, you may want to make sure your image is in YCbCr format before you start throwing away image channels.

Upvotes: 0

ArtemStorozhuk
ArtemStorozhuk

Reputation: 8725

Have you tried to get values of result image? Like this:

for (int i=0; i<result.rows; i++)
{
    for (int j=0; j<result.cols; j++)
    {
        cout << result.at<int>(i,j) << endl;
    }
}

I have converted (also used convertTo) random gray-scale single-channel image to CV_32S (it is a signed 32bit integer value for each pixel) my output was like this:

80
111
132

And when I tried to show it I also get black image. From documentation:

If the image is 16-bit unsigned or 32-bit integer, the pixels are divided by 256. That is, the value range [0,255*256] is mapped to [0,255].

So if you divide these small numbers to 255 than you will get 0 (int type). That's why imshow displays black image.

Upvotes: 3

Related Questions