opencv read jpeg image from buffer - c++

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.

Related

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 cvSaveImage() increases the size of image

i am loading an image and just saving the same image but with a different name using cvSaveImage(). After saving the size of the newly saved image gets increased. can anyone tell me why and how to avoid it?? here is my code:
int main(){
IplImage* src = cvLoadImage("test.jpg", 0);
cvSaveImage("reTest.jpg", src);
return 0;
}
thanks.
There are different methods of compression and coding combined in JPEG.
Most likely your original image used a different compression/coding than standard openCV parametrization for cvSaveImage.
Try this:
IplImage* src = cvLoadImage("test.jpg", 0);
cvSaveImage("reTest.jpg", src);
IplImage* reSrc = cvLoadImage("reTest.jpg",0);
cvSaveImage("reTest2.jpg", reSrc);
if reTest.jpg and reTest2.jpg have the same size, openCV does not increase the filesize but just uses a different compression level or sth.
You would have to find out the compression level and coding of your original file and save it with these same parameters, maybe with a different library than openCV.
It is because of low JPEG compression factor used by default in OpenCV. Here is how to to pass custom compression factor - OpenCV cvSaveImage Jpeg Compression Factor .

converting a UYVY FFmpeg

I want to read and show a video using opencv. I've recorded with Direct-show, the Video has UYVY (4:2:2) codec, since opencv can't read that format, I want to convert the codec to an RGB color model, I readed about ffmpeg and I want to know if it's possible to get this done with it ? if not if you a suggestion I'll be thankful.
As I explained to you before, OpenCV can read some formats of YUV, including UYVY (thanks to FFmpeg/GStreamer). So I believe the cv::Mat you get from the camera is already converted to the BGR color space which is what OpenCV uses by default.
I modified my previous program to store the first frame of the video as PNG:
cv::Mat frame;
if (!cap.read(frame))
{
return -1;
}
cv::imwrite("mat.png", frame);
for(;;)
{
// ...
And the image is perfect. Executing the command file on mat.png reveals:
mat.png: PNG image data, 1920 x 1080, 8-bit/color RGB, non-interlaced
A more accurate test would be to dump the entire frame.data() to the disk and open it with an image editor. If you do that keep in mind that the R and B channels will be switched.

Bitmap to Iplimage conversion produce wrong color

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);

Convert YUV to lossy compression with OpenCV

How would I go about converting an image in YUV colorspace to a JPEG image?
I have a raw image data saved in a char* variable:
char* frame = (char*)camera->getFrame(); // YUV colorspace image data
I need to convert this to a JPEG image data instead. I don't want to save it to disk because I will be sending it in a stream.
OpenCV itself does not export this functionality. Cleanest is to use libjpeg for encoding. See the answers to these questions:
Convert IplImage into a JPEG without using CvSaveImage in OpenCV
OpenCV to use in memory buffers or file pointers
Check the opencv src for the file cvcolor.cpp. This has all the color conversions in it.
I suggest you modify the existing routines near this line:
/* BGR/RGB -> YCrCb */
They are almost exactly what you need for YUV encoding. if its 4:4:4 and not 4:2:2 or 4:1:1
for jpg compression
The jpg encoder and decoder are in grfmt_jpeg.cpp which happens to #include "jpeglib.h"
You can call these directly