5
votes

I'm trying to have a webcam take a picture of someone's face in BGR, convert the picture into HSV, and analyze these HSV values that will later be used in a skin detection algorithm. Unfortunately, the picture seems to be analyzed in BGR, even after I try to convert it using cvtColor().

I use the code below to test whether or not I'm using the right color space. Note the part where I try to set saturation and value to 0:

Mat faceROI = findFace(first); //basic Mat, region of interest for face (code not included)

Mat temp;
faceROI.convertTo(temp, CV_8UC3); //making sure this has right no. of channels and such

CvScalar s;

IplImage face_ipl = temp; //new header
IplImage* aNew = cvCreateImage(cvGetSize(&face_ipl), face_ipl.depth, 3);

cvCvtColor(&face_ipl, aNew, CV_BGR2HSV);

for(int x = 0; x < faceROI.cols; x++){
    for (int y = 0; y < faceROI.rows; y++){
        s = cvGet2D(aNew, x, y);

        //vvvvvvvvvvv
        s.val[1] = 0; //should be saturation
        s.val[2] = 0; //should be value
        //^^^^^^^^^^^

        cvSet2D(aNew, x, y, s);
    }
}

Mat again(aNew); //<--- is this where something is set back to BGR?
imshow("white", again);

cvReleaseImage(&aNew);

This produces a completely blue picture of my face, so it seems likes I'm editing the G and R channels of a BGR image, instead of the S and V channels of an HSV image. (I'd post the image, but this is my first post so I don't have enough reputation yet.)

Does anybody know why this is happening? Any and all thoughts are appreciated.

1
So where are you converting the image back from HSV to BGR?sgarizvi
That's the heart of my question...I don't think I ever do convert back to BGR, but the results seem to indicate that that's what's going on.Connor
No matter what color space the image has, the imshow function will always interpret the image as a simple RGB or BGR image. As you are assigning 0 to the S and V channels, only the H channel remains which corresponds to B in a BGR image. So for imshow, again is a BGR image with values only in blue channel. That's why you are seeing blue output.sgarizvi
Workaround------> add cvtColor(again,again,CV_HSV2BGR) before imshow.sgarizvi
Your workaround suggestion really helped - it gave me the expected results. (I changed the value parameter to 255 and kept saturation at 0; my code with your suggestion produces a pure white window, which makes sense.) Thanks for your help!Connor

1 Answers

12
votes

You're mixing up the C++ Mat style with the old C IplImage*, this makes it confusing to see what exactly is going on. Here is the code to turn inputImage into HSV:

Mat fullImageHSV;
cvtColor(inputImage, fullImageHSV, CV_BGR2HSV);

Be aware that the OpenCV HSV values are H from 0-180 while S and V are from 0-255 while other programs tend to use different values. ALso note that OpenCV is unable to show HSV images normally, this distorts the color because they are being interpreted as RGB.