OpenCV+QML实现视频采集(一)

一、下载安装OpenCV
1、linux: sudo apt install libopencv-dev
2、winodws:打开OpenCV官网:http://opencv.org/Release下载OpenCV
二、 主要源码
1、在pro中引用lib

 LIBS += -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_videoio -lopencv_imgcodecs
2、创建OpenCVCamera类
因为需要把采集的每一帧图像缓存起来显示,所以用到了QQuickImageProvider,注释部分是测试opcencv算法,
大家可以放开试用一下效果。
opencvcamera.h
#ifndef OPENCVCAMERA_H
#define OPENCVCAMERA_H

#include <QObject>
#include <QImage>
#include <QQuickImageProvider>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

class OpenCVCamera : public QObject, public QQuickImageProvider
{
    Q_OBJECT
public:
    explicit OpenCVCamera(QObject *parent = nullptr);
    ~OpenCVCamera();
    //返回的image
    QImage  requestImage(const QString& id, QSize* size, const QSize& requestedSize) override;
    //设置图像
    static void setImage(const QImage &image);
signals:
    void imageReady(QImage img);

public slots:
    void startCapture();
    void stopCapture();
    void gaussian_noise(Mat &image);
    void add_salt_pepper_noise(Mat &image);

private:
    cv::VideoCapture m_cap;
    static  QImage ms_image;
};

#endif // OPENCVCAMERA_H

opencvmera.cpp

#include "opencvcamera.h"
#include <QDebug>
#include <QThread>
#include <QCoreApplication>

QImage OpenCVCamera::ms_image(":/ima/EMSbig.png");



OpenCVCamera::OpenCVCamera(QObject *parent) :  QQuickImageProvider(QQmlImageProviderBase::Image)
{

}

OpenCVCamera::~OpenCVCamera()
{
    stopCapture(); // 程序退出时释放资源
}

QImage  OpenCVCamera::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
    qDebug()<<"ImageProvider::requestImage"<<id;
    return ms_image ;

}


void OpenCVCamera::setImage(const QImage &image)
{
    qDebug()<<"ImageProvider::setImage"<<image;
    ms_image = image;
    //这里为了检查图像是否正常,做了一个保存
   // ms_image.save(QCoreApplication::applicationDirPath()+"/ima/2.jpg");
}



void OpenCVCamera::startCapture()
{
    if (!m_cap.isOpened()) { // 如果尚未打开摄像头,则打开默认摄像头(设备号为0)
         m_cap.open(0);
    }
    Mat frame; // 创建Mat对象用于存储图像帧
    while (true) {
       // QThread::currentThread()->msleep(80); // too much wait
        m_cap >> frame; // 从摄像头读取一帧图像
        if (!frame.empty()) { // 如果成功读取到了图像
             //Mat转QImage 颜色
             cvtColor(frame,frame,CV_BGR2RGB);
//             中值滤波
             medianBlur(frame, frame, 5);
//             gaussian_noise(frame);
//             Mat result1, result2, result3, result4;
//             blur(frame, result1, Size(5, 5));
//             imshow("result-1", result1);

//             GaussianBlur(frame, result2, Size(5, 5), 0);
//             imshow("result-2", result2);

//             medianBlur(frame, result3, 5);
//             imshow("result-3", result3);

            // fastNlMeansDenoisingColored(frame, result4, 15, 15, 10, 30);
          //   imshow("result-4", result4);
//             Mat retumage;
             //高斯模糊
//             GaussianBlur(frame,retumage,Size(5,5),0,0);
             //双倍模糊
//             cv::bilateralFilter(frame,retumage,15,120,10,4);
             //灰度化
//             cvtColor(frame,retumage,CV_BGR2GRAY);
//             cvtColor(retumage,retumage,CV_GRAY2BGR);

             QImage img(frame.data, frame.cols, frame.rows, static_cast<int>(frame.step), QImage::Format_RGB888); // 将Mat转换成QImage
//             imagemEditada.save(QCoreApplication::applicationDirPath()+"/ima/2.jpg");
             OpenCVCamera::setImage(img);
             emit imageReady(img); // 发射信号,将QImage对象传递给QML界面
        }
        if (waitKey(30) >= 0) { // 每30ms读取一帧
        }

    }
}

void OpenCVCamera::stopCapture()
{
    if (m_cap.isOpened()) { // 如果摄像头已打开,则释放资源
         m_cap.release();
    }
}

void OpenCVCamera::gaussian_noise(Mat &image)
{
    Mat noise = Mat::zeros(image.size(), image.type());
    randn(noise, (15, 15, 15), (30, 30, 30));
    Mat dst;
    add(image, noise, dst);
    imshow("gaussian noise", dst);
    dst.copyTo(image);
}

void OpenCVCamera::add_salt_pepper_noise(Mat &image)
{
    RNG rng(12345);
    int h = image.rows;
    int w = image.cols;
    int nums = 10000;
    for (int i = 0; i < nums; i++) {
        int x = rng.uniform(0, w);
        int y = rng.uniform(0, h);
        if (i % 2 == 1) {
            image.at<Vec3b>(y, x) = Vec3b(255, 255, 255);
        }
        else {
            image.at<Vec3b>(y, x) = Vec3b(0, 0, 0);
        }
    }
    imshow("salt pepper", image);
}

3 、在main.cpp注册OpenCVCamera类到QML上下文中,注册 ImageProvider, 并且指定前缀, 该前缀在qml中使用, image:// 前缀表示 图片来自于 ImageProvider

qmlRegisterType<OpenCVCamera>("com.example.opencv", 1, 0, "OpenCVCamera");
engine.addImageProvider("imageprovider",new OpenCVCamera());

4、在main.qml中

                          Button{
                              text: "Start"
                               onClicked: {
                                  camera.startCapture();

                              }
                          }
                          Button{
                              text: "Stop"
                              onClicked: {
                                  camera.stopCapture();
                              }
                          }
        Image{
            id: bigImageItem
            width: parent.height
            height:parent.height
            cache: false
            anchors.right: parent.right  //基于父控件靠右对齐
            source: "qrc:/windowRes/EMSbig.png"
            fillMode: Image.PreserveAspectCrop
        }
OpenCVCamera {
    id: camera
    property int imgid: 1
    onImageReady: {
        imgid++;
        bigImageItem.source = "image://imageprovider/" +imgid;//需要使用 source: "image://标识符/图片id" 的格式来加载;
    }
}

这次就写到这里,我想做两部分来写视频采集,第一部分写怎么实现,第二部分写有关移植到开发板上运行,因为我的开发板没有支持uvc,看不到效果,下次实现了就分享给大家。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值