I'd really like to attach to my web camera, process the frames I get out of it, and then display the processed frame in a window with some super-imposed markings.
The strategy I've been trying is to have a QGraphicsView with a QGraphicsScene that has a QGraphicsPixmap added. I then use a custom VideoSurface to grab frames. Right now I'm trying to just transfer the frames to the QGraphicsView (no extra markings or processing) but if I call setPixmap the program will crash just after the frame handler returns. If I skip the call to setPixmap, it doesn't crash. Could anyone point me in the right direction?
MainWindow
::MainWindow(QWidget *parent
) : ui(new Ui::MainWindow),
frame(640, 480)
{
ui->setupUi(this);
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
cam = new QCamera(cameras.first(), this);
cam->load();
frame_grabber = new CameraFrameGrabber();
cam->setViewfinder(frame_grabber);
cam->setCaptureMode(QCamera::CaptureViewfinder);
connect(frame_grabber,
SIGNAL(frameAvailable
(QImage)),
this,
SLOT(handleFrame
(QImage)));
cam->start();
frame_timer.start();
scene->addItem(pix);
ui->gv_viewfinder->setScene(scene);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::handleFrame(const QImage& img)
{
frame_times.push_back(frame_timer.elapsed());
frame_timer.restart();
if (frame_times.size() > 10) frame_times.pop_front();
int frame_count = frame_times.size();
int frame_total = 0;
for(int i = 0; i < frame_count; ++i)
{
frame_total += frame_times[i];
}
double fps = 0;
if (frame_count)
{
fps = (frame_total / frame_count);
}
ui->sb_fps->setValue(fps);
bool good_pix = frame.convertFromImage(img);
if (good_pix) pix->setPixmap(frame);
this->update();
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
frame(640, 480)
{
ui->setupUi(this);
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
cam = new QCamera(cameras.first(), this);
cam->load();
frame_grabber = new CameraFrameGrabber();
cam->setViewfinder(frame_grabber);
cam->setCaptureMode(QCamera::CaptureViewfinder);
connect(frame_grabber, SIGNAL(frameAvailable(QImage)), this, SLOT(handleFrame(QImage)));
cam->start();
frame_timer.start();
scene = new QGraphicsScene();
pix = new QGraphicsPixmapItem(frame);
scene->addItem(pix);
ui->gv_viewfinder->setScene(scene);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::handleFrame(const QImage& img)
{
frame_times.push_back(frame_timer.elapsed());
frame_timer.restart();
if (frame_times.size() > 10) frame_times.pop_front();
int frame_count = frame_times.size();
int frame_total = 0;
for(int i = 0; i < frame_count; ++i)
{
frame_total += frame_times[i];
}
double fps = 0;
if (frame_count)
{
fps = (frame_total / frame_count);
}
ui->sb_fps->setValue(fps);
bool good_pix = frame.convertFromImage(img);
if (good_pix) pix->setPixmap(frame);
this->update();
}
To copy to clipboard, switch view to plain text mode
bool CameraFrameGrabber::present(const QVideoFrame &frame)
{
if (frame.isValid()) {
QVideoFrame cloneFrame(frame);
cloneFrame.map(QAbstractVideoBuffer::ReadOnly);
const QImage image
(cloneFrame.
bits(),
cloneFrame.width(),
cloneFrame.height(),
QVideoFrame::imageFormatFromPixelFormat(cloneFrame .pixelFormat()));
emit frameAvailable(image);
cloneFrame.unmap();
return true;
}
return false;
}
bool CameraFrameGrabber::present(const QVideoFrame &frame)
{
if (frame.isValid()) {
QVideoFrame cloneFrame(frame);
cloneFrame.map(QAbstractVideoBuffer::ReadOnly);
const QImage image(cloneFrame.bits(),
cloneFrame.width(),
cloneFrame.height(),
QVideoFrame::imageFormatFromPixelFormat(cloneFrame .pixelFormat()));
emit frameAvailable(image);
cloneFrame.unmap();
return true;
}
return false;
}
To copy to clipboard, switch view to plain text mode
Bookmarks