Bitmap to Iplimage conversion produce wrong color - c++

i am trying to convert a bitmap to opencv image i am using pinvoke by sending the Bitmap.Scan0 and in the unmanaged side i am creating iplimage by using the byte array the solution is seems to work but not always ! only if i created the image on my pc using my grahpic device but it fails on another the image colors seems to be not right and the image is shifted i am suspecting that i should transfer the bitmap to DIB how can this done ?
IplImage* image= cvCreateImage(cvSize(width,height),depth,3)
memcpy(image->imageData,(uchar*)(bitmap),width*height*3);

IplImage stores pixels in the BGR order while HBITMAP expects them to be RGB.
Luckely, for you, the whole IplImage can be converted from BGR to RGB with:
cvCvtColor(image, image, CV_BGR2RGB);

Related

OpenCV create YUV420 or grayscale Mat object from YUYV pixelformat video frame

I am trying to process video frames from a Qt application. The input from the QML Camera is of format YUYV and I could not set it to something else like YUV420 by default. I need to capture the frame and create a Mat object of YUV420 or grayscale format.
I have tried cvtColor with the following codes and they all crashed during runtime -
COLOR_YUV2GRAY_YVY
COLOR_YUV2RGB_YUYV
COLOR_YUV2GRAY_YUYV
Any idea how I can do this?
So after playing around with the color conversion codes a bit this is the solution I found to be working for me.
cv::Mat img = cv::Mat(m_videoHeight, m_videoWidth, CV_8UC2, input->bits());
cv::Mat gray;
cv::cvtColor(img, gray, cv::COLOR_YUV2GRAY_YVYU);
This converts the given YUYV Mat object - img to a grayscale Mat object - gray. input->bits() refers to the first bit of the video frame buffer.

saving grayscale images as video in C++

In my code, there are created cv::Mat images whose format is CV_16UC1. I have a cv::VideoWriter object and insert created grayscale images into it. However, I have completely black video as a result. If I change the cv::Mat format to CV_8UC1 everything works as expected. Is there anything that I am missing?

How to create an image in opencv from a buffer that holds image in RGBA format

I have an image in a buffer that hold an image with format of RGBA. I want to create an openCV image from it (cv::Mat), but it seems that I can not do this.
The code that I have is this:
cv::Mat image=cv::Mat(cvSize(Width,Height), CV_8UC4,Buffer, cv::Mat::AUTO_STEP).clone();
The main problem is that since OpenCV is saving its images in BGRA format, and the buffer has image in RGBA format, the colours of generated image is not correct.
I know that I can convert the image to BGRA format, but is there any way that I can create an image in OpenCV that holds images in RGBA format?
You can use cvtColor to convert the Mat from RGBA to BGRA. And if you will do it right after creation of the "original" Mat from the buffer, you need not to use clone(), as anyway the new buffer will be allocated for the converted image.
cv::Mat image=cv::Mat(cvSize(Width,Height), CV_8UC4, Buffer, cv::Mat::AUTO_STEP);
cv::Mat converted;
cvtColor(image, converted, CV_RGBA2BGRA);
you create an image in RGBA format with your code, that's no problem.
The problem is that OpenCV assumes BGR(A) images when saving the image or using openCV methods.
Maybe you can use special libraries (png lib, jpeg lib etc) to save images directly in RGB(A) format, instead. OpenCV really is about BGR for displaying or saving the images, since no color model is assigned to the images (it's just a x bit 3/4 channel image, whatever color model is used must be maintained by the user).

opencv read jpeg image from buffer

I have an unsigned char* buffer containing data of a jpeg image. I would like to display that image using c++ and opencv. If i do:
Mat img(Size(640, 480), CV_8UC3, data);
namedWindow("image", 1);
imShow("image", img);
I get a noisy mess of pixels.
I suppose it's because the data is jpeg (with a header). Because this works:
Mat imgbuf(Size(640, 480), CV_8UC3, data);
Mat img = imdecode(imgbuf, CV_LOAD_IMAGE_COLOR);
BUT I cannot use the imdecode function as it is from highgui.h which is based upon GTK 2, and in my project I use GTK 3.
So, how can I display the buffer data? Is there a way to decode the jpeg image other than imdecode in opencv, if that's the problem. I don't really want to have to rebuild opencv with Qt...
Any other suggestions?
(Using Linux)
I have seen many responses to this question around on the net saying that you should call libjpeg directly and bypass OpenCV's imread() routine.
This is NOT necessary! You can use imdecode() to decode a raw image buffer from memory. The way to do it is NOT intuitive, and isn't documented enough to help people trying to do this for the first time.
If you have a pointer/size for your raw file data (fread() directly from the .jpg, .png, .tif, files, etc...
int nSize = ... // Size of buffer
uchar* pcBuffer = ... // Raw buffer data
// Create a Size(1, nSize) Mat object of 8-bit, single-byte elements
Mat rawData( 1, nSize, CV_8UC1, (void*)pcBuffer );
Mat decodedImage = imdecode( rawData /*, flags */ );
if ( decodedImage.data == NULL )
{
// Error reading raw image data
}
That's IT!
Hope this helps someone in the future.
I have decompressed the JPEG image using libjpeg using the standard procedure described in the libjpeg API documentation under 'Decompression details'.
After having decompressed the data you can use it to construct the cv::Mat. Mind you, the decompressed image is in RGB format, whereas openCV uses a BGR format so a cvtColor() operation with format CV_RGB2BGR is needed.

cv::Mat detect PixelFormat

I'm trying to use pictureBox->Image (Windows Forms) to display a cv::Mat image (openCV). I want to do that without saving the Image as a file ('cause i want to reset the image every 100ms).
I just found that topic here: How to display a cv::Mat in a Windows Form application?
When i use this solution the image appears to be white only. I guess i took the wrong PixelFormat.
So how do figure out the PixelFormat i need? Haven't seen any Method in cv::Mat to get info about that. Or does this depend on the image Source i use to create this cv::Mat?
Thanks so far :)
Here i took a screen. Its not completely white. So i guess there is some color info. But maybe i'm wrong.
Screen
cv::Mat.depth() returns the pixel type, eg. CV_8U for 8bit unsigned etc.
and cv::Mat.channels() returns the number of channels, typically 3 for a colour image
For 'regular images' opencv generally uses 8bit BGR colour order which should map directly onto a Windows bitmap or most Windows libs.
SO you probably want system.drawing.imaging.pixelformat.Format24bppRgb, I don't know what order ( RGB or BGR) it uses but you can use the opencv cv::cvtColor() with CV_BGR2RGB to convert to RGB
Thanks for the help! The problem was something else.
I just did not allocate memory for the Image Object. So there was nothing to really display.
Using cv::Mat img; in the headerFile and img = new cv::Mat(120,160,0); in Constructor (ocvcamimg Class) got it to work. (ocvcamimg->captureCamMatImg() returns img).