OpenCV how to put jpeg image buffer to cvShowImage - c++

I have a JPG image in buffer and I would try to show it with cvShowImage. This is not working, however:
// buff is a JPEG image with 640*480 dimensions
IplImage* fIplImageHeader;
fIplImageHeader = cvCreateImageHeader(cvSize(640, 480), 8, 1);
fIplImageHeader->imageData = (char *)buff;
cvShowImage("Window 1", fIplImageHeader);
cvWaitKey();
cvReleaseImageHeader(&fIplImageHeader);
I get a black window with that.

Looks like you forgot to set widthStep
|-- int widthStep; // size of aligned image row in bytes
|-- int imageSize; // image data size in bytes = height*widthStep

Related

Create video file using sequence of QPixmap in QT Creator- C++

I have QWidget (named as screenshotLabel) and continuously it's content is changing.I can get that lable content to qpixmap (named as originalPixmap) as bellow.
originalPixmap = QPixmap();
QPixmap pixmap(screenshotLabel->size());
this->render(&pixmap);
originalPixmap = pixmap;
Now I want to save it as a video file.But I could not able to do it.How can I save QWidget content as a video file?
I found a way to generate video using OpenCV VideoWriter.I leave comments in the code that describe what is happening.
originalPixmap = pixmap;
qImageSingle = originalPixmap.toImage(); // Convert QPixmap to QImage
// Get QImage data to Open-cv Mat
frame = Mat(qImageSingle.height(), qImageSingle.width(), CV_8UC3, qImageSingle.bits(), qImageSingle.bytesPerLine()).clone();
namedWindow("MyVideo", CV_WINDOW_AUTOSIZE);
imshow("MyVideo", frame);
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
compression_params.push_back(9);
try {
imwrite("alpha2.png", frame, compression_params);
VideoWriter video("out2.avi", CV_FOURCC('M','J','P','G'), 10, Size(qImageSingle.width(), qImageSingle.height()), true);
for(int i=0; i<100; i++){
video.write(frame); // Write frame to VideoWriter
}
}
catch (runtime_error& ex) {
fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what());
}

OpenCV cv::Mat release for free Memory

I try to release from memory an image cv::Mat but with poor results.
Before the creation of the image, Memory is 20,3 MB
cv::Mat image = [self cvMatWithImage:originalUIImage];
Now Memory is 54,3 MB..and in next line, for testing, i release the cv::Mat
image.release();
I see that memory is 37,2 MB, why?
Method cvMatWithImage :
- (cv::Mat)cvMatWithImage:(UIImage *)image
{
CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
CGFloat cols = image.size.width;
CGFloat rows = image.size.height;
cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels
CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to backing data
cols, // Width of bitmap
rows, // Height of bitmap
8, // Bits per component
cvMat.step[0], // Bytes per row
colorSpace, // Colorspace
kCGImageAlphaNoneSkipLast |
kCGBitmapByteOrderDefault); // Bitmap info flags
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);
CGContextRelease(contextRef);
return cvMat;
}
Not sure if this is the entire problem, but you probably want to use CV_8UC3 instead of CV_8UC4, since kCGImageAlphaNoneSkipLast has only 3 channels.

How to flip a QImage

What is the right way to flip/mirror a QImage? The following snippet does not work.
//allocate buffer
BYTE* pRgb32Buffer = new BYTE[width*height* 4];
//create paint device
QImage img = QImage(pRgb32Buffer , width, height, getStride(width, pixelFormat), QImage::Format_RGB32);
//do some drawing on image (works!)
QPainter painter(&img);
painter.drawText(10, 50, QString("some text"));
//mirrore image (doesn't mirror the orignal buffer!!!)
img = img.mirrored(false,true);
//doesn't work either
//QImage mirrored = img.mirrored();
//img = mirrored;
//mirrored.detach();
A solution using QImage::mirrored():
memmove(pRgb32Buffer, img.mirrored().bits(),img.byteCount());
I have this working code to mirror a QPixmap onto an QImage.
QPixmap* source = //... Getting my pixmap form somewhere...
QImage target(QSize(source->width(), source->height()), QImage::Format_ARGB32);
QPainter painter(&target);
QTransform transf = painter.transform();
transf.scale(-1, 1);
painter.setTransform(transf);
painter.drawPixmap(-source->width(), 0, *source);
The source contains the mirrored pixmap after that code. You should be able to do the same with QImageand the QPainter::drawImage function as alternative.
Optionally you can save the file if you want (make sure you have the imageformats dll's or it won't write):
QImageWriter writer("c:\\theimage.tiff", "tiff");
writer.setCompression(1);
writer.write(target);

Converting a color image to grayscale issue in OpenCV

I'm facing a problem, when I'm trying to convert a color image to a grayscale. The error is: "bad argument (array should be CvMat or IplImage) in cvGetSize", but I can manage to load the original color image and display it, when I'm commenting all the lines, which are related to the grayscale one. How can I fix this error ?.
#include <opencv\cv.h>
#include <opencv\highgui.h>
#include <iostream>
#include <stdio.h>
int main(int argc, char** argv)
{
//Loading the color image
IplImage* frame = cvLoadImage("lena.jpg");
//Converting the color image to grayscale
IplImage* grayframe = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
cvCvtColor(frame, grayframe, CV_RGB2GRAY);
//Creating a window for color image
cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE);
//Creating a window for grayscale image
cvNamedWindow("Example2", CV_WINDOW_AUTOSIZE);
// Showing the color image
cvShowImage("Example1", frame);
// Showing the grayscale image
cvShowImage("Example2", grayframe);
//Showeing for X seconds
cvWaitKey(2000);
cvReleaseImage(&frame);
cvDestroyWindow("Example1");
cvReleaseImage(&grayframe);
cvDestroyWindow("Example2");
return 0;
}
why Iplimage ?
try with Mat, if you would like to extend the examples in future.
Mat image = imread("lena.jpg");
Mat gray;
cvtColor(image,gray,CV_BGR2GRAY);
this would with ease, will give you gray scale image.
But, if there is a specific reason to use C api, then,
the problem is at
IplImage* grayframe = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
I don't know the exact reason for that, but, I could give you an alternative to run your code.
int x= frame->width, y=frame->height;
IplImage* grayframe = cvCreateImage(cvSize(x,y), IPL_DEPTH_8U, 1);
Tyr it, it might work for you

wxImage and draw raw rgb bytes

I am programming image viewer as school task and I cant use any libraries for reading or manipulating images. First I started with bmp format. I have created class for handle this type of file. As GUI framework I am using wxWidgets.
So I have plain rgb bytes array, prepared for wxImage constructor
wxImage(int width, int height, unsigned char* data, bool static_data = false).
Problem is that when I convert it to wxBitmap and draw to dc it's ignoring rgb values a draw only black picture. I really do not know what could be a problem. This is my code for draw image:
DrawImage(wxDC &dc)
{
BYTE *rgbArray = bmpFile->GetRGB();
wxSize imageSize = wxSize(bmpFile->GetSize().w,bmpFile->GetSize().h);
wxImage image = wxImage(imageSize, &rgbArray);
wxBitmap bitmap = wxBitmap(image);
dc.DrawBitmap(bitmap,5,5, false);
}
And this is on paint event:
void OnPaint(wxPaintEvent& event)
{
wxAutoBufferedPaintDC dc(canvas);
dc.SetBackground( wxBrush(canvas->GetBackgroundColour()));
dc.Clear();
DrawImage(dc);
}
rgbArray is filled with right values, I checked it multiple times.
Thanks for any help :)
Thats because you are probably calling this function, because you are passing a BYTE**.
wxImage (const wxSize &sz, bool clear=true)
to call the other overload, removing the & might help
wxImage image = wxImage(imageSize, rgbArray);
To make the code exception safe, it must be rewritten slightly. I don't know whether bmpFile returns a new buffer or a pointer to its own data buffer. If it doesn't return a new buffer then you must make your own copy because wxImage takes ownership of the buffer. see wxImage
DrawImage(wxDC &dc)
{
wxSize imageSize = wxSize(bmpFile->GetSize().w,bmpFile->GetSize().h);
wxImage image = wxImage(imageSize, bmpFile->GetRGB() );
wxBitmap bitmap = wxBitmap(image);
dc.DrawBitmap(bitmap,5,5, false);
}
or
DrawImage(wxDC &dc)
{
std::unique_ptr<BYTE> rgbData( bmpFile->GetRGB() );
wxSize imageSize = wxSize(bmpFile->GetSize().w,bmpFile->GetSize().h);
wxImage image = wxImage(imageSize, rgbData.release()) );
wxBitmap bitmap = wxBitmap(image);
dc.DrawBitmap(bitmap,5,5, false);
}