firefly-rk3399 开发记录4-自定义QCameraViewfinder

1.QCameraViewfinder

QCamera的取景器,用于显示摄像头抓到的数据,前面所使用的就是这个。但是现在遇到一个需求,比如在一些场合中,需要在显示图像上打水印,OSD等信息,比如在人脸检测场景中一帮会要求识别画框,这里这里没有提供hook方式,不行,probe是并行的,并不会影响到显示这里。看有些博客上说继承一下QCameraViewfinder然后覆写paintevent

void QCameraViewfinderPri::paintEvent(QPaintEvent *e)
{    
	QCameraViewfinder::paintEvent (e);
    QPainter painter(this);
    painter.setPen(Qt::red);
    painter.drawRect(50, 50, 100, 100);
}

试了一下,并没有效果。最后发现说可以自己实现Viewfinder,在这样就可以控制显示了。

2.自定义viewfinder

继承的说明,网络上比较多,就不详细说明了。这里没有给显示策略,只是做了一次捕获操作。在继承过程中必须要实现纯虚函数present 和supportedPixelFormats

class QSmartViewFinder : public QAbstractVideoSurface
{
    Q_OBJECT
public:
    QSmartViewFinder(QObject *parent = NULL);
    ~QSmartViewFinder();
signals:
    void showFrame(QVideoFrame image);
protected:
    QList<QVideoFrame::PixelFormat> supportedPixelFormats(
    QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const override;
    bool present(const QVideoFrame &frame) override;
};

supportedPixelFormats用于表示可以支持的格式

QList<QVideoFrame::PixelFormat> QSmartViewFinder::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{
    QList<QVideoFrame::PixelFormat > pixelFormats;
    pixelFormats.append(QVideoFrame::Format_RGB32);
    pixelFormats.append(QVideoFrame::Format_YUV420P);
    return pixelFormats;
}

present 在每帧数据来的时候,都会进入一次,这里主要就是讲获取到的帧通过信号发送出去,QVideoFrame里面并没有存储真的数据,所以在传递时并不会带来什么开销。

bool QSmartViewFinder::present(const QVideoFrame &frame)
{
    if (frame.isValid()){
        QVideoFrame cloneFrame(frame);
        emit showFrame(cloneFrame);
        return true;
    }
    return false;
}

3.设置自定义的viewfinder

QSmartViewFinder *finder = new QSmartViewFinder(this);

    m_camera.reset(new QCamera(cameraInfo));
    //m_camera->setViewfinder(ui->widgetShowImage);
    m_camera->setViewfinder(finder);
    connect(finder,&QSmartViewFinder::showFrame,[this](QVideoFrame f){
        if(!f.isValid())
            return;
        f.map(QAbstractVideoBuffer::ReadOnly);
        cv::Mat img(f.height() * 3 / 2, f.width(), CV_8UC1, f.bits());
        cv::Mat mat;
        cvtColor(img, mat, cv::COLOR_YUV420p2BGR);
        QImage image(mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        //这就可以绘图了
        QDateTime now = QDateTime::currentDateTime();
        ui->label->setPixmap(QPixmap::fromImage(create_image_text(image,now.toString(),40,QPoint(50,50))));
        f.unmap();
    });

这里就取消了之前设置的QCameraViewfinder,而是用了自定义的设置,由于设置输入的帧格式是YUV的,QImage并不支持YUV的转换,所以这里引入了一次opencv的转换,刚开始比较担心带来性能上的开销,后面发现并不会,显示十分流畅。这里采用自定义viewfinder之后,其实QVideoProbe就用不到了,毕竟自己就已经可以捕获每一帧数据了。

这里有个疑问,QImage明明设置是RGB888的,但是在mat转换的时候,需要设置为BGR,而不是RGB,不然显示色彩会有错。

4.文字绘制函数

QPen pen;
        QFont font;
        QImage tmp = base;
        pen.setStyle(Qt::DashDotLine);
        pen.setColor(Qt::white);
        pen.setCapStyle(Qt::RoundCap);
        pen.setJoinStyle(Qt::RoundJoin);

        font.setPixelSize(size);
        font.setBold(true);

        QPainter painter(&tmp);

        QFontMetrics fm = painter.fontMetrics();
        painter.setPen(pen);
        painter.setFont(font);
        painter.drawText(origin,text);
        painter.end();

        return tmp;

猜你喜欢

转载自blog.csdn.net/huahuang1508/article/details/107862753
今日推荐