Displaying Grayscale in PictureBox/PixelFormat
I am using OpenCV 2.4.6 on a Windows 8 64 bit machine with VS2012 C++/cli and trying to make a WinForms application that displays frames captured from a webcam in a picturebox. So far, this has been working for color images but when I try and display a image converted to grayscale, the displayed image seems positionally correct but kaleidoscopic color wise rather than grayscale.
void DrawCVImageDetect(System::Windows::Forms::PictureBox^ PBox, cv::Mat& colorImage)
{
System::Drawing::Graphics^ graphics = PBox->CreateGraphics();
System::IntPtr ptr(colorImage.ptr());
System::Drawing::Bitmap^ b;
switch(colorImage.type())
{
case CV_8UC3: // non-grayscale images are correctly displayed here
b = gcnew System::Drawing::Bitmap(colorImage.cols,colorImage.rows,colorImage.step,
System::Drawing::Imaging::PixelFormat::Format24bppRgb,ptr);
break;
case CV_8UC1: // grayscale images are incorrectly displayed here
b = gcnew System::Drawing::Bitmap(colorImage.cols,colorImage.rows,colorImage.step,
System::Drawing::Imaging::PixelFormat::Format8bppIndexed,ptr);
break;
default:
// error message
break;
}
System::Drawing::RectangleF rect(0,0,(float)PBox->Width,(float)PBox->Height);
graphics->DrawImage(b,rect);
}
When I call this with a regular Mat captured from the webcam, it works fine. When I convert that same Mat to a grayscale, I get the weird colors. I am converting to grayscale using cvtColor(OriginalMat,OriginalMat,RGB2GRAY). The output from this does not appear to be the same channel type as the input (i.e., a CV_8UC3 going in appears to come out as a CV_8UC1). I have also forced the output to 3 channels using cvtColor(OriginalMat,OriginalMat,RGB2GRAY,3). The fact that just the colors are off makes me think that there is something with the color indexing/premultiplication but I have tried many of the the different pixelformat types and nothing seems to work. Thanks in advance for any help.
Before you use the grayscale you need to build a three layer image with each layer containing the grayscale info. It will work perfectly then.
I am not sure what you mean. The OriginalMat is a CV_8UC3. So it has three channels. The output of the cvtColor should be the same type but is being converted to a CV_8UC1. As I say, when I force the output of the cvtColor to three channels (using cvtColor(OriginalMat,OriginalMat,RGB2GRAy,3) is still get the weird colors.
No you have to make a mat with 3 channels and use mixchannels to clone the data into the actual channels. Just using the cvt function will screw your data up. Example of code that I use:
I am probably slow, but this seems to have no effect. The sequence you are using seems no different than gray_3channels = gray.clone(). In any event, when I implement this without calling cvtColor, I just get the same color image (which is what I would expect). If I subsequently call cvtColor, I get the weird colors I had initially. It is probably just me.
It is actually different. If you apply gray.clone() you will try to copy a CV_8UC1 format into a CV_8UC3 format. OpenCV will actually allow this since it stores images as long vector elements and loops through them using the specified type size. However, what my code does is taking the same grayscale values for the red, green and blue channel and mix them. This will make a CV_8UC3 from CV_8UC1 images. By selecting the same pixel values for each channel, it will produce a grayscale.