Use QCamera and QCameraInfo to work with a frame grabber card and a camera link cam.
-
Hello! I am in the process of developing an application which handles video signal acquisition with use of a frame grabber card and a line scan camera. The camera is connected to the board via a camera link cable. I am using a driver provided by the manufacturer to interface with the frame grabber and I have some code which handles the acquisition process. I am able to use Qt on top of that implementation to receive the buffer data and create a single frame still image from the cam. I can also confirm that the camera works and grants a live-preview in a proprietary application.
I would like to utilize Qt Multimetia and Multimediawidgets to grab the signal and display it in my GUI. I have followed the Camera Example but that only seems to work with cameras embedded in the laptop system. I am not seeing that particular camera I need to use in my system. The following check hints there are no cameras:
bool checkCameraAvailability() { if (QCameraInfo::availableCameras().count() > 0) return true; else return false; }
Therefore I can't create a viewfinder widget to display the picture. Could you advise how to get that working in Qt?
-
@szumial
What do you mean? Image from local picture file or from raw data in the memory?
Anyway both can construct a QImage / QPixmap.
QPixmap can be displayed by a QLabel easily (but not very smooth when scaling).
Or if you want you can write your own widget withQPainter::drawPixmap
inpaintEvent
. -
Ok, in my acquisition sequence, I do collect raw data which is stored in a buffer. I would like to be able to have two widgets - the first one giving users a live-preview of what the camera can see, the second one being able to store a particular frame after executing an acquisition sequence. For that still image I used the QImage / QPixmap approach and I see it works fine. Are you saying it is possible to have a pixmap with continuous refresh?
-
@szumial said in Use QCamera and QCameraInfo to work with a frame grabber card and a camera link cam.:
Are you saying it is possible to have a pixmap with continuous refresh?
No, if you have a new frame, you need to create a new QPixmap.
QImage has this constructor
QImage::QImage(uchar *data, int width, int height, int bytesPerLine, QImage::Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr)
So it can be created using an existing memory buffer.
Then use
QPixmap::fromImage
to create a new QPixmap from the QImage.If you use the QLabel approach, call
QLabel::setPixmap
to set the new QPixmap.
Any old QPixmap set to this label should be released automatically.Also QImage / QPixmap doesn't support YUV so if you have YUV frames you need to convert them to RGB data first.
-
Allright, what you described sounds like what I need. I already have this code which displays a single frame on a pushbutton click, so I might be able to play with it.
void MainWindow::on_pushButton_draw_clicked() { imageFrame->InitializeImage(*m_bufferData, (m_SizeX/12), (m_SizeY/4), m_BufferPitch); QGraphicsScene *scene = new QGraphicsScene; scene->addPixmap(imageFrame->ImageToPixmap()); ui->graphicsView->setScene(scene); } void ImageFrame::InitializeImage(uchar *m_pImageData, int imageSizeX, int imageSizeY, int imageBufferPitch) { myImage = new QImage(m_pImageData, imageSizeX, imageSizeY, imageBufferPitch, QImage::Format_Mono); } QPixmap ImageFrame::ImageToPixmap() { QPixmap pixmap = QPixmap::fromImage(*myImage); return pixmap; }
This does not auto-update the contents of the pixmap, even though I am in continuous acquisition mode. I think I would like to create my own widget which constructs a QImage and takes care of displaying the image to reuse it in different parts of the application. Does this example make sense?
-
You mean your raw data buffer is continuously updating so you expect the QPixmap will refresh automatically?
Of course it can't! That's what a video does. :)
You need to be informed whenever a new frame is updated to the buffer, then create a new QPixmap after that.
And you don't need to save the QImage (also not safe when created with external buffer), it is just kind of a wrapper from raw data to QPixmap.
If you need to keep a QImage to reuse, then you'd better save one from QImage::copy(), this will create a new QImage with its own buffer. -
Hi and welcome to devnet,
If you would like to make use of QtMultimedia in such a case, you would need to implement your own QCamera backend that will get the data out of the frame grabber and then send it through the QtMultimedia pipeline.
It might look overwhelming but it's in fact not that hard and it has the added bonus to make your camera accessible both in widget and QML based applications.
-
Hello @SGaist and thank you for joining the thread! That is what I initially wanted to do, but started looking for other ideas when I noticed that QCamera would not work for me out of the box. In fact, I will likely need to support several different grabber boards, therefore it might make sense to have my own backend implemented. Can you hint me where to start with this? I would like to expose my driver data to QCamera somehow.
-
@szumial
Wow, good for you! I've never written any backend / plugin myself but I think you should start from:
https://doc.qt.io/qt-5/plugins-howto.html#the-high-level-api-writing-qt-extensions
https://doc.qt.io/qt-5/qmediaserviceproviderplugin.html
And there'are many examples of other backends from the qt multimedia plugins source code: $QT_SRC_DIR/qtmultimedia/src/plugins -
Hello @szumial I am new to Qt and working on a very similar application. I am using a frame grabber board from National Instruments connect to a camera via the camera link. I was wondering if you could provide some guidance on how you implemented image updates in your "live-preview" display. I was planning on using a QThread to receive the images from the frame grabber board but then I wasn't sure of the best approach to displaying the image. From what I understand QPixmap is not thread safe. Thanks.
-
@aconsig
A lot of time has passed since the thread has been posted, but regardless, here is my final solution. I ended up with using a QLabel that was refreshed with a specified frequency by a QTimer. The timeout signal triggered getting available frames stored in a buffer that I have created, then set a correct pixmap to that QLabel object. This solution was fast and flexible enough for me. -