win7_64bits下QT使用openCV库(2)

27 篇文章 37 订阅

博主QQ:1356438802

QQ群:473383394——UVC&OpenCV47



本文实验平台:win7_64bits + OpenCV 2.4.10 + QT Creator 3.4.1 + QT 5.4.2(MSVC 2013, 32bit)


一、先讲一个题外的东西,但是跟QT和video相关的。

QT5开始有QCamera类,可以很方便的实现camera的预览、拍照、录像。

示例下载:http://download.csdn.net/detail/luoyouren/9570139

#include "dialog.h"
#include "ui_dialog.h"


Dialog::Dialog(QWidget *parent) :
    QDialog(parent)
{
    this->resize(1280, 720);

    camera = NULL;
    view_finder = NULL;
    camera_image_capture = NULL;

    QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
    if(cameras.count() < 1)
    {
        qDebug() << "There's not camera available!";
        return;
    }

    camera = new QCamera();
    camera_image_capture = new QCameraImageCapture(camera);

    //用于实时预览
    view_finder = new QCameraViewfinder();

    capture_button = new QPushButton();
    save_button = new QPushButton();
    exit_button = new QPushButton();

    QHBoxLayout *main_layout = new QHBoxLayout();
    QVBoxLayout *v_layout = new QVBoxLayout();

    //用于显示拍照截图, 初始大小为320x240
    display_label = new QLabel();
    display_label->setFixedSize(320, 240);
    //label自适应其内容的大小进行缩放
    display_label->setScaledContents(true);

    //垂直布局,容纳窗口右边的控件
    v_layout->addWidget(display_label);
    v_layout->addStretch();
    v_layout->addWidget(capture_button);
    v_layout->addWidget(save_button);
    v_layout->addWidget(exit_button);

    //水平布局,主窗口: 左边是预览区域
    main_layout->addWidget(view_finder);
    main_layout->addLayout(v_layout);

    //连接信号和槽函数
    connect(capture_button, &QPushButton::clicked, this, &Dialog::captureImage);
    connect(save_button, &QPushButton::clicked, this, &Dialog::saveImage);
    connect(exit_button, &QPushButton::clicked, this, &Dialog::close);

    connect(camera_image_capture, &QCameraImageCapture::imageCaptured, this, &Dialog::displayImage);

    /*
     * 我的阶段性理解:
     * QCameraImageCapture::CaptureToFile
     * capture时,可以指定文件名路径,在SIGNAL(imageCaptured)后会自动保存图片文件;
     * 如果空的文件名路径,将按照默认规则和默认路径保存图片——"库\图片"
     *
     * QCameraImageCapture::CaptureToBuffer
     * capture时,图像保存在buffer里面,用户在SIGNAL(imageCaptured)后自行手动保存图片
     *
     */
    camera_image_capture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);

    camera->setCaptureMode(QCamera::CaptureStillImage);
    camera->setViewfinder(view_finder);
    camera->start(); //启动摄像头

    this->setLayout(main_layout);

    //设置控件名称
    this->translateLanguage();

    mPixelFmt = camera_image_capture->bufferFormat();
    qDebug() << "bufferFormat is " << mPixelFmt;

    //
    QList<QVideoFrame::PixelFormat> pFList = camera_image_capture->supportedBufferFormats();
    qDebug() << "supported bufferFormat = " << pFList.count();
    foreach (QVideoFrame::PixelFormat pf, pFList) {
        qDebug() << "supported bufferFormat is " << pf;
    }

    QImageEncoderSettings imageSettings;

    qDebug() << "1 current codec is " << camera_image_capture->encodingSettings().codec();

    //暂时没有效果
    imageSettings.setCodec("image/png");
    imageSettings.setResolution(640, 480);
    camera_image_capture->setEncodingSettings(imageSettings);
}

Dialog::~Dialog()
{
    close_camera();
}

void Dialog::translateLanguage()
{
    this->setWindowTitle("testCapture");
    capture_button->setText(tr("capture"));
    save_button->setText(tr("save"));
    exit_button->setText(tr("exit"));
}

void Dialog::displayImage(int id, QImage image)
{
    mPixelFmt = camera_image_capture->bufferFormat();
    qDebug() << "image id = " << id << "; bufferFormat is " << mPixelFmt;

    qDebug() << "2 current codec is " << camera_image_capture->encodingSettings().codec();


    display_label->setPixmap(QPixmap::fromImage(image));
}

void Dialog::captureImage()
{
    //截图
    camera_image_capture->capture();
}

void Dialog::saveImage()
{
    const QPixmap *pixmap = display_label->pixmap();
    if(pixmap)
    {
        pixmap->save("F:\\a.jpg");
    }
}

void Dialog::close_camera()
{
    if((NULL != camera) && (QCamera::ActiveState == camera->state()))
    {
        camera->stop();
        delete camera;
        delete view_finder;
        delete camera_image_capture;

    }
}





二、在前面一篇文章中,我利用opencv 2.4.10已经初步达到了usb camera的预览功能。

现在我对这个示例进行一些优化,并且对cvtColor这个格式转换函数做测试,看看它参数变化对图像产生什么影响。具体效果需要大家自己去实验体会!

之所以做这个事情,是因为我要把这个程序移植到Android平台——《我的Opencv4Android添加V4L2支持的移植记录(1)》,Android上的ImageView只支持ARGB8888格式,opencv出来的frame是RGB888格式,要想办法转换格式。


示例下载:http://download.csdn.net/detail/luoyouren/9570162

#include "dialog.h"
#include "ui_dialog.h"
#include <QDebug>

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    mCapture = NULL;
    mTimer = NULL;
    mFrame = NULL;
    mIsOpen = false;

    mTimer = new QTimer(this);

    if(NULL != mTimer)
    {
        qDebug() << "4545454545454\n";
        //50ms超时,就去取图片帧
        connect(mTimer, SIGNAL(timeout()), this, SLOT(getFrame()));
    }

    qDebug() << "3333333333333333\n";

    //:/pic/pic/desktop.jpg
//    QImage image = QImage(":/pic/pic/desktop.jpg");
//    ui->label->setPixmap(QPixmap::fromImage(image));

    qDebug() << "444444444444444\n";
}

Dialog::~Dialog()
{

    uninit();

    if(NULL != mTimer)
    {
        delete mTimer;
        mTimer = NULL;
    }
    qDebug() << "--------------- ~Dialog\n";
    delete ui;
}

void Dialog::init()
{
    if(mIsOpen == false)
    {
        mCapture = NULL;

        mCapture = cvCaptureFromCAM(0);
        if(NULL == mCapture)
        {
            qDebug() << "init camera failed!\n";
            return;
        }

        ui->BtnOpen->setText(QString::fromLocal8Bit("关闭"));

        if(NULL != mTimer)
        {
            mTimer->start(50);   //50毫秒取一帧图片
        }
        mIsOpen = true;
    }
    else
    {
        uninit();
    }
}

void Dialog::uninit()
{
    qDebug() << "uninit camera!\n";
    if(mIsOpen == true)
    {
        if(NULL != mTimer)
        {
            mTimer->stop();
        }

        if(NULL != mCapture)
        {
            cvReleaseCapture(&mCapture);
        }

        ui->BtnOpen->setText(QString::fromLocal8Bit("打开"));
        mIsOpen = false;

        qDebug() << "uninit camera done!\n";
    }
}

void Dialog::on_BtnOpen_clicked()
{
    init();
}

void Dialog::getFrame()
{
    if(NULL == mCapture)
    {
        qDebug() << "mCapture has been released!";
        return;
    }

    mFrame = NULL;
    mFrame = cvQueryFrame(mCapture); //取图片帧
    if(NULL == mFrame)
    {
        qDebug() << "cvQueryFrame failed";
        return;
    }

    int w = mFrame->width;
    int h = mFrame->height;
    //    int imgSize = frame->imageSize;

#if 1
    qDebug() << "RGBA w= " << w << " h= " << h;
    Mat imgData(h, w, CV_8UC3, mFrame->imageData);
    Mat imgBGRA;

    //    cvtColor(imgData, imgBGRA, CV_RGB2BGRA);  //颜色反相
    //    cvtColor(imgData, imgBGRA, CV_BGR2BGRA);    //颜色正常

    cvtColor(imgData, imgBGRA, CV_RGB2RGBA);    //颜色正常
    //    cvtColor(imgData, imgBGRA, CV_BGR2RGBA);    //颜色反相
    qDebug() << "imgData.elemsize= " << imgData.elemSize() << "  imgBGRA.elemsize= " << imgBGRA.elemSize();

    //注意rgbSwapped也会影响图像
    QImage image = QImage((const uchar*)imgBGRA.data, w, h, QImage::Format_ARGB32);


#else
    qDebug() << "RGB888\n";
    //usb camera取出来的数据就是RGB888
    //将图片转换为Image对象,rgbSwapped是为了显示效果色彩好一些。
    QImage image = QImage((const uchar*)frame->imageData, w, h, QImage::Format_RGB888).rgbSwapped();

#endif

    ui->label->setPixmap(QPixmap::fromImage(image));
}



三、前面用的都是opencv1的C函数调用

下面我要使用opencv2中的C++API进行usb camera预览、录像,主要是VideoCapture和VideoWriter两个类的使用。


示例下载:http://download.csdn.net/detail/luoyouren/9570171

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->label->setScaledContents(true);  //fit video to label area

    rate = 30;
    timer = NULL;
    timer = new QTimer(this);
    if(NULL != timer)
    {
        connect(timer, SIGNAL(timeout()), this, SLOT(nextFrame()));
    }
}

MainWindow::~MainWindow()
{
    if (capture.isOpened())
    {
        //decide if capture is already opened; if so,close it
        capture.release();
    }

    if (writer.isOpened())
    {
        writer.release();
    }

    if(NULL != timer)
    {
        if(timer->isActive())
        {
            timer->stop();
        }
        delete timer;
    }

    delete ui;
}



QImage MainWindow::Mat2QImage(cv::Mat cvImg)
{
    QImage qImg;

    //3 channels color image
    if(cvImg.channels() == 3)
    {
        cv::cvtColor(cvImg, cvImg,CV_BGR2RGB);
        qImg =QImage((const unsigned char*)(cvImg.data),
                     cvImg.cols, cvImg.rows,
                     cvImg.cols*cvImg.channels(),
                     QImage::Format_RGB888);
    }
    else if(cvImg.channels() == 1)
    {
        //grayscale image
        qImg =QImage((const unsigned char*)(cvImg.data),
                     cvImg.cols,cvImg.rows,
                     cvImg.cols*cvImg.channels(),
                     QImage::Format_Indexed8);
    }
    else
    {
        qImg =QImage((const unsigned char*)(cvImg.data),
                     cvImg.cols,cvImg.rows,
                     cvImg.cols*cvImg.channels(),
                     QImage::Format_RGB888);
    }

    return qImg;
}

///auto get next frame
void MainWindow::nextFrame()
{
    capture >> frame;
    if (!frame.empty())
    {
        image = Mat2QImage(frame);
        ui->label->setPixmap(QPixmap::fromImage(image));
    }
}

void MainWindow::on_btnOpenFile_clicked()
{
    if (capture.isOpened())
    {
        //decide if capture is already opened; if so,close it
        capture.release();
    }

    //get video file
    QString filename =QFileDialog::getOpenFileName(this,tr("Open Video File"),".",tr("Video Files(*.avi *.mp4 *.flv *.mkv)"));

    capture.open(filename.toLocal8Bit().data());
    if (capture.isOpened())
    {
        rate= capture.get(CV_CAP_PROP_FPS);
        qDebug() << "rate = " << rate;
        if(NULL != timer)
        {
            //set timer match with FPS
            timer->setInterval(1000/rate);
            timer->start();
        }
    }
}

void MainWindow::on_btnOpenCamera_clicked()
{
    if (capture.isOpened())
    {
        //decide if capture is already opened; if so,close it
        capture.release();
    }

    //open the default camera
    capture.open(0);
    if (capture.isOpened())
    {
//        rate= capture.get(CV_CAP_PROP_FPS);
//        qDebug() << "rate = " << rate;
        if(NULL != timer)
        {
            //set timer match with FPS
            timer->setInterval(1000/30);
            timer->start();
        }
    }
}

void MainWindow::on_btnProcess_clicked()
{
    cv::Mat cannyImg ;
    cv::Canny(frame, cannyImg, 0, 30, 3);
    cv::namedWindow("Canny");
    cv::imshow("Canny", cannyImg);
}

void MainWindow::on_btnStartREC_clicked()
{
    writer.open("./myrec.avi", CV_FOURCC('P','I','M','1'), /*capture.get(CV_CAP_PROP_FPS)*/30, cv::Size(frame.cols, frame.rows),true);

    int t=100;
    while(t--) {writer.write(frame);} //record 100 frames

    //if successfully start videoWriter, disable the button
    ui->btnStartREC->setDisabled(true);

}

void MainWindow::on_btnStopREC_clicked()
{

    if (writer.isOpened())
    {
        writer.release();
    }
    ui->btnStartREC->setDisabled(false);

}
参考文章: http://www.cnblogs.com/annt/p/ant003.html#3380613


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值