Does anyone know how to convert QVideoFrame to OpenCV cv::Mat in QT6?
I have event where video frame arrived from video camera.
void videoFrameChanged(const QVideoFrame &frame)// frame from QCamera
{
QImage qImg=frame.toImage();//<<-- slow
cv::Mat m=Qimage2Mat_shared(qImg);
...
}
I know how to convert QImage to cv::Mat, but here used very slow function: frame.toImage().
How to convert directly QVideoFrame to cv::Mat ?
Related
Hi I am trying to draw a contour to a base64 encoded qbytearray by converting it to cv mat and revert it back to qbyte array to display on qml.
While the first part is working correclty, I can't seem to convert the cv mat to qbytearray back properly
the code that I am using now is
cv::Mat final_img;
cv::Mat dst;
cv::resize(final_img, final_img, final_img.size());
cv::cvtColor(final_img, dst, cv::COLOR_BGR2BGRA);
QByteArray data = QByteArray::fromRawData(reinterpret_cast<char*>(dst.data), 592355);
decoded_image = "data:image/jpeg;base64,";
decoded_image.append(QString::fromLatin1(data.toBase64().data()));
I get a correct format of base64encoded bytearray but gets the following error
Unsupported image format
Any help will be appreciated! Thanks
I've created a filter extending QAbstractVideoFilter and
QVideoFilterRunnable and I've overrided the
QVideoFrame run(QVideoFrame* input, const QVideoSurfaceFormat &surfaceFormat, RunFlags flags)`
method
The problem is that QVideoFrame format is Format_YUV420P and has no handle. I need to convert it into a CV_8UC1 in order to use OpenCV algorithms.
Which is the best way to accomplish this?
First you need to create a cv::Mat which has an API for initializing using data pointer as:
cv::Mat img = cv::Mat(rows, cols, CV_8UC3, input.data/*Change this to point the first element of array containing the YUV color info*/)
Now since the img is initialized with YUV color data, you may use various cvtColor modes to convert the YUV mat to other formats, for converting it to gray-scale you may try:
cv::Mat gray;
cv::cvtColor(img, gray, cv::COLOR_YUV2GRAY_I420);
I'm working on a homework for my Digital Image Processing class, and I'm using OpenCV with QT Framework.
I've created a class ImageDisplay, which is as sub class of the QWidget class.
I've using OpenCV to manipulate a grayscale image, and then creating a QImage object from the Mat object. After that I use the QWidget::drawImage() to draw the image. But sometimes it shows a distorted, angled image.
I was experimenting and discovered that it has something to do with the image dimensions.
For instance, this image with 320x391 pixels is rendered normally
But if change the dimension to 321x391 (using Gimp), it shows up like this:
This is the code for the paintEvent method:
void ImageDisplay::paintEvent(QPaintEvent *){
QPainter painter(this);
Mat tmp;
/* The mat in the next line is a Mat object that contains the image data */
cvtColor(mat, tmp, CV_GRAY2BGR);
QImage image(tmp.data, tmp.cols, tmp.rows, QImage::Format_RGB888);
painter.drawImage(rect(), image);
}
Does anyone has a clue what is the problem and how to fix it?
Thanks in advance!
I think you may need to specify the step of the image (number of bytes per line) when creating QImage in the fourth parameter:
QImage image((const uchar*) tmp.data, tmp.cols, tmp.rows, tmp.step, QImage::Format_RGB888);
I want to display 3 channel cv::Mat on Qt interface and usually I use this expressions:
e
QImage qImage = QImage( (uchar*)cvImage.data, cvImage.cols, cvImage.rows, cvImage.cols*3, QImage::Format_RGB888 );
QPixmap pixmap = QPixmap::fromImage(qImage);
myLabel.setPixmap(pixmap);
But conversion to QPixmap is slow enough. Do you know guys how to avoid the conversion? May be the function setImage can help, but I don't know how to use it...
I'm trying to show LiveView image in real time. I use EDSDK 2.14 + Qt5 + opencv+mingw32 under Windows. I'm not very sophisticated in image processing so now I have the following problem. I use example from Canon EDSDK and all was ok until this part of code:
//
// Display image
//
I googled a lot of examples but all of them was written on C# or MFC or VB. Also I found advise to use libjpegTurbo for decompressing image and then showing it using opencv. I tried to use libjpegTurbo but failed to undestand what to do :(. Maybe somebody here have code example of the conversion LiveView stream to opencv Mat or QImage (because I use Qt)?
Here is what worked for me after following the SAMPLE 10 from the Canon EDSDK Reference. It's a starting point for a more robust solution.
In the downloadEvfData function, I replaced the "Display Image" part by the code bellow:
unsigned char *data = NULL;
EdsUInt32 size = 0;
EdsSize coords ;
// get image coordinates
EdsGetPropertyData(evfImage, kEdsPropsID_Evf_CoordinateSystem, 0, sizeof(coords), &coords);
// get buffer pointer and size
EdsGetPointer(stream, (EdsVoid**)&data);
EdsGetLenth(stream, &size);
//
// release stream and evfImage
//
// create mat object
Mat img(coords.height, coords.width, CV_8U, data);
image = imdecode(img, CV_LOAD_IMAGE_COLOR);
I've also changed the function signature:
EdsError downloadEvfData(EdsCameraRef camera, Mat& image)
And in the main function:
Mat image;
namedWindow("main", WINDOW_NORMAL);
startLiveView(camera);
for(;;) {
dowloadEvfData(camera, image);
imshow("main", image);
if (waitkey(10) >= 0);
break;
}
Based on the Canon EDSDKs example, you may append your EdsStreamRef 'stream' data with its correct length into a QByteArray. Then, use for example the following to parse the raw data from the QByteArray as a JPG into a new QImage:
QImage my_image = QImage::fromData(limagedata,"JPG"); Once it's in a QImage you can convert it into a OpenCV cv::Mat (see How to convert QImage to opencv Mat)
Well it depends on the format of the liveview-stream.
There must be some kind of delimiter in it and you need then to convert each image and update your QImage with it.
Check out this tutorial for more information: Canon EDSDK Tutorial in C#
QImage img = QImage::fromData(data, length, "JPG");
m_image = QImageToMat(img);
// -----------------------------------------
cv::Mat MainWindow::QImageToMat(QImage& src)
{
cv::Mat tmp(src.height(),src.width(),CV_8UC4,(uchar*)src.bits(),src.bytesPerLine());
cv::Mat result = tmp.clone();
return result;
}
// -------------------------
void MainWindow::ShowVideo()
{
namedWindow("yunhu",WINDOW_NORMAL);
while(1)
{
requestLiveViewImage();
if(m_image.data != NULL)
{
imshow("yunhu", m_image);
cvWaitKey(50);
}
}
}