使用opencv在Qt中实现卡通化视频处理

一、前言

本文主要在Qt中使用opencv进行编程,实现了简易的摄像头播放及其卡通化处理功能,编程环境为Qt5.5.1+opencv2.4.6,实现的关键是将Mat变量转换为QImage变量,并使用QLabel进行显示。

二、环境配置

首先需要安装Qt creator 5.5.1和下载解压opencv2.4.6,为了能够在Qt中调用opencv中的函数,必须用cmake对openc2.4.6进行编译,如何编译就不详解了,编译之后得到的库我将其放在E:\software\OpenCV-2.4.6.0\opencv。

三、新建工程

打开Qt creator,使用版本为5.5.1,新建Qt Widgets Application,选择如下


在pro文件中添加编译之后的opencv路径

INCLUDEPATH+=E:\software\OpenCV-2.4.6.0\opencv\build\include\opencv\

             E:\software\OpenCV-2.4.6.0\opencv\build\include\opencv2\

             E:\software\OpenCV-2.4.6.0\opencv\build\include

 

LIBS +=E:\software\OpenCV-2.4.6.0\opencv\MinGW\lib\libopencv_core246.dll.a\

            E:\software\OpenCV-2.4.6.0\opencv\MinGW\lib\libopencv_highgui246.dll.a\

           E:\software\OpenCV-2.4.6.0\opencv\MinGW\lib\libopencv_imgproc246.dll.a\

           E:\software\OpenCV-2.4.6.0\opencv\MinGW\lib\libopencv_calib3d246.dll.a\    

           E:\software\OpenCV-2.4.6.0\opencv\MinGW\lib\libopencv_contrib246.dll.a\

           E:\software\OpenCV-2.4.6.0\opencv\MinGW\lib\libopencv_features2d246.dll.a\

           E:\software\OpenCV-2.4.6.0\opencv\MinGW\lib\libopencv_flann246.dll.a\

           E:\software\OpenCV-2.4.6.0\opencv\MinGW\lib\libopencv_gpu246.dll.a\

           E:\software\OpenCV-2.4.6.0\opencv\MinGW\lib\libopencv_legacy246.dll.a\

           E:\software\OpenCV-2.4.6.0\opencv\MinGW\lib\libopencv_ml246.dll.a\

           E:\software\OpenCV-2.4.6.0\opencv\MinGW\lib\libopencv_objdetect246.dll.a\

           E:\software\OpenCV-2.4.6.0\opencv\MinGW\lib\libopencv_video246.dll.a

打开widget.ui,按照下图拖入3个按钮与一个Label标签,编程的目的是点击打开摄像头按钮可将视频显示于label中,当然稍微改动也可以打开其他已存在的视频片段。点击视频卡通化按钮即可将视频卡通化处理,点击关闭摄像头按钮则关闭摄像头。


四、代码简介

在widget.h中定义如下槽函数与数据成员

private slots:
    void openCamera();
    void readFrame();
    void closeCamera();
    QImage cvMat2QImage(const cv::Mat& mat);  //将Mat数据结构转换为QImage
    void cartoonifyImage( Mat & , Mat & );    //视频卡通化处理
    void startCaroonify();                    //令flag为true

private:
    Ui::Widget *ui;
    QTimer    *timer;
    QImage    img;
    VideoCapture camera;
    Mat frame,dstImage;
    bool flag ;
在widget.cpp中,各主要函数定义如下所示:
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    timer   = new QTimer(this);
    flag = false;
    connect(timer, SIGNAL(timeout()), this, SLOT(readFrame()));
    connect(ui->pushButton_1, SIGNAL(clicked()), this, SLOT(openCamera()));
    connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(startCaroonify()));
    connect(ui->pushButton_3, SIGNAL(clicked()), this, SLOT(closeCamera()));
}

Widget::~Widget()
{
    delete ui;
}
void Widget::openCamera()
{

    camera.open(0);
    if (!camera.isOpened())
    {
        std::cerr <<"Could not access the camera or video!"<<
        std::endl;
        exit(1);
    }
    camera.set(CV_CAP_PROP_FRAME_WIDTH ,640);
    camera.set(CV_CAP_PROP_FRAME_HEIGHT , 480); //设置分辨率

    timer->start(33);  //显示时间控制

}
void Widget::readFrame()
{

    camera >>frame;

    if (frame.empty())
    {
        std::cerr<<"ERROR: Couldn't grab a camera frame."<<
        std::endl;
        exit(1);
    }
    if (flag)
        cartoonifyImage(frame , dstImage);
    else
        frame.copyTo(dstImage);
    img = cvMat2QImage(dstImage);
    ui->label->resize(frame.cols,frame.rows);
    ui->label->setPixmap(QPixmap::fromImage(img));

}
void Widget::closeCamera()
{
    timer->stop();
    camera.release();
    exit(1);  //结束退出
}

void Widget::startCaroonify()
{
    flag = !flag;
}
QImage Widget::cvMat2QImage(const cv::Mat& mat)
{
    // 8-bits unsigned, NO. OF CHANNELS = 1
    if(mat.type() == CV_8UC1)
    {
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        // Set the color table (used to translate color indexes to qRgb values)
        image.setColorCount(256);
        for(int i = 0; i < 256; i++)
        {
            image.setColor(i, qRgb(i, i, i));
        }
        // Copy input Mat
        uchar *pSrc = mat.data;
        for(int row = 0; row < mat.rows; row ++)
        {
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        return image;
    }
    // 8-bits unsigned, NO. OF CHANNELS = 3
    else if(mat.type() == CV_8UC3)
    {
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        return image.rgbSwapped();
    }
    else if(mat.type() == CV_8UC4)
    {
        qDebug() << "CV_8UC4";
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        return image.copy();
    }
    else
    {
        qDebug() << "ERROR: Mat could not be converted to QImage.";
        return QImage();
    }
}
void Widget::cartoonifyImage(  Mat &srcColor , Mat &dst)
{
    Mat gray;
    cvtColor(srcColor , gray ,CV_BGR2GRAY);  //默认彩色格式是BGR
    const int MEDIAN_BLUR_FILTER_SIZE = 7;
    medianBlur(gray ,gray ,MEDIAN_BLUR_FILTER_SIZE);  //中值滤波器去噪
    Mat edges;
    const int LAPLACIAN_FILTER_SIZE = 5;
    Laplacian(gray ,edges , CV_8U ,LAPLACIAN_FILTER_SIZE);

    Mat mask;
    const int EDGES_THRESHOLD = 65;
    threshold(edges , mask ,EDGES_THRESHOLD,255 ,THRESH_BINARY_INV); //生成边缘掩码mask
    mask.copyTo(dst);

    Size sizeSrc = srcColor.size();  //算法较为复制,为提高效率,将原图像长宽缩减一半进行双边滤波处理
    Size smallSize;
    smallSize.width = sizeSrc.width/2;
    smallSize.height = sizeSrc.height/2;
    Mat smallImage = Mat(smallSize ,CV_8UC3);
    cv::resize(srcColor ,smallImage ,smallSize ,0,0,INTER_LINEAR);

    Mat tmp = Mat(smallSize ,CV_8UC3);
    int repetitions = 3;
    for(int i = 0; i<repetitions ;i++)
    {
        int ksize = 9;
        double sigmaColor = 11;
        double sigmaSpace = 5;
        bilateralFilter(smallImage ,tmp ,ksize,sigmaColor,sigmaSpace);
        bilateralFilter(tmp ,smallImage ,ksize,sigmaColor,sigmaSpace);
    }

    Mat bigImg;
    cv::resize(smallImage ,bigImg,sizeSrc ,0 ,0 ,INTER_LINEAR);
    dst.setTo(0); //全置为0
    bigImg.copyTo(dst , mask);//掩码中黑色部分不会被复制,生成 素描掩码+ 彩色图画 = 卡通图画

}

五、实现效果



六、源代码与参考资料

源代码下载链接为:http://download.csdn.net/detail/ap1005834/9504595

参考资料为:

http://blog.chinaunix.net/uid-23381466-id-3826748.html

Mat类转换为QImage参考自http://blog.csdn.net/liyuanbhu/article/details/46662115

卡通化处理代码参考自书本《深入理解OpenCV:实用计算机视觉项目解析》


























评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值