Qt + opencv的学习(一)

一、opencv和Qt的环境搭建。

网上有很多资料,所以我也是依照网上资料进行,主要是对opencv库的编译以及Qt对opencv的使用。

需要下载所需版本的opencv的源码,另外需要一个cmake工具。 我下载的opencv版本是3.2.0版本,通过cmake后在使用VS2013进行编译得到最终的库文件。

然后在Qt中就可以像一般的添加库方式添加。

另外想说明的是,最好是将编译得到的文件,放到一个指定目录,将其中的头文件和库文件路径添加到环境变量中,这样会方便你的开发。

(要注意的是,如果你之后改变了这个文件的路径,记得环境变量也要进行修改,不然Qt中程序崩溃而且不容易发现这个问题)

二、opencv的初步接触

推荐大家去了解opencv的基础数据类型。

以下是我学习时用到的两个博主的网站:

源码阅读 以及 一些类类型说明

另外推荐一个网站,但是都是英文需要慢慢阅读。 opencv的api说明

三、练习代码

我习惯的学习方法是,练习一些基础功能、函数。并且在运行中记录错误增加自己理解的备注,方便以后复查和看代码时快速理解。

所以这里都是记录的一些练习,有自己的一些注释。

我的Qt的pro文件配置,以后不再重复:

INCLUDEPATH += $$PWD/install/include \
                $$PWD/install/include/opencv \
                $$PWD/install/include/opencv2

CONFIG(debug, debug|release): {
LIBS += -L$$PWD/install/x86/vc12/lib
LIBS += -lopencv_calib3d320d \
-lopencv_core320d \
-lopencv_features2d320d \
-lopencv_flann320d \
-lopencv_highgui320d \
-lopencv_imgcodecs320d \
-lopencv_imgproc320d \
-lopencv_ml320d \
-lopencv_objdetect320d \
-lopencv_photo320d \
-lopencv_shape320d \
-lopencv_stitching320d \
-lopencv_superres320d \
-lopencv_video320d \
-lopencv_videoio320d \
-lopencv_videostab320d
} else:CONFIG(release, debug|release): {
LIBS += -L$$PWD/install/x86/vc12/lib
LIBS += -lopencv_calib3d320 \
-lopencv_core320 \
-lopencv_features2d320 \
-lopencv_flann320 \
-lopencv_highgui320 \
-lopencv_imgcodecs320 \
-lopencv_imgproc320 \
-lopencv_ml320 \
-lopencv_objdetect320 \
-lopencv_photo320 \
-lopencv_shape320 \
-lopencv_stitching320 \
-lopencv_superres320 \
-lopencv_video320 \
-lopencv_videoio320 \
-lopencv_videostab320
}
View Code

练习代码:

#include "widget.h"
#include <QApplication>
#include <opencv2/opencv.hpp>
#include <stdio.h>
#include <QDebug>

#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif

using namespace std;
using namespace cv;

void createAlphaMat(Mat& mat){
    for(int i = 0; i < mat.rows; i++){
        for(int j = 0; j < mat.cols; j++){
            Vec4b &rgba = mat.at<Vec4b>(i, j);
            rgba[0] = UCHAR_MAX;
            rgba[1] = saturate_cast<uchar>(float((mat.cols) - j)
                                           / ((float)mat.cols) * UCHAR_MAX);
            rgba[2] = saturate_cast<uchar>(float((mat.cols) - i)
                                           / ((float)mat.rows) * UCHAR_MAX );
            rgba[3] = 0;

        }
    }

}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //Widget w;
    //w.show();
    /**显示图片
    Mat image = imread("C:\\Users\\zhangenhao\\Desktop\\IMG_000000011.jpg");
    Mat im(4,4,CV_8U,Scalar(101,102,103));
    cvNamedWindow("windows", CV_WINDOW_NORMAL);
    imshow("windows", image);
    //返回矩阵通道的数量
    qDebug() << "mat channels:" << image.channels();
    waitKey(0);
    */

    /**自画图像并保存
    Mat mat(480, 640, CV_8UC4);
    createAlphaMat(mat);

    namedWindow("image", CV_WINDOW_AUTOSIZE);
    imshow("image", mat);

    //保存失败
    vector<int> compression_params;
    compression_params.resize(2);
    compression_params[0] = CV_IMWRITE_PNG_COMPRESSION;
    compression_params[1] = CV_IMWRITE_PNG_COMPRESSION;
    //compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
    qDebug() << compression_params.size();
    imwrite("./genera.png", mat, compression_params);
    **/

    /** 方框滤波 均值滤波 高斯滤波
    namedWindow("原图", CV_WINDOW_NORMAL);
    namedWindow("Box效果图");
    namedWindow("Blur效果图");
    namedWindow("Gauss效果图");

    Mat srcImg = imread("C:\\Users\\zhangenhao\\Desktop\\IMG_000000011.jpg");
    imshow("原图", srcImg);

    Mat Boxout;
    boxFilter(srcImg, Boxout, -1, Size(7, 7));
    imshow("Box效果图", Boxout);


    Mat Blurout;
    blur(srcImg, Blurout, Size(7, 7));
    imshow("Blur效果图", Blurout);

    Mat Gauss;
    GaussianBlur(srcImg, Gauss, Size(7, 7), 0, 0);
    imshow("Gauss效果图", Gauss);
    **/

    /**图像制式转化 cvtColor
    Mat image = imread("C:\\Users\\zhangenhao\\Desktop\\IMG_000000011.jpg");
    Mat ret;
    cvtColor(image, ret, CV_RGB2GRAY);//转为灰度图
    cvNamedWindow("windows", CV_WINDOW_NORMAL);

    imshow("windows", ret);
    //返回矩阵通道的数量
    qDebug() << "mat channels:" << image.channels();
    cout << "mat :" << endl << image << endl;
    waitKey(0);

    **/

    /**
    //unsigned char 0~255
    //char -128~127
    Mat A = (Mat_<unsigned char>(3, 3) << 1,2,3,4,5,6,7,8,9);
    cout << "A =" <<  endl << A <<endl;
    cout << "A.t() =" << endl << A.t()  << endl;
    Mat B = A.t();
    cout << "B =" << endl << B << endl;
    //row,column 赋值某个像素点
    B.at<unsigned char>(1, 2) = 10;
    cout << "after assigning value to B." << endl;
    cout << "A = " << endl << A << endl;
    cout << "B = " << endl << B << endl;

    Mat C = A.clone();
    //全部+1,减法也适用
    C += 1;
    cout << "C += 1 ->" << endl << C << endl;
    C -= 1;

    //按照参数类型确定最大值最小值
    C = A.clone();
    C += 250;
    cout << "C += 250 ->" << endl << C << endl;
    C = A.clone();
    C -= 250;
    cout << "C -= 250 ->" << endl << C << endl;
    C = A.clone();

    // 全部*10
    C *= 10;
    cout << "C *= 10 ->" << endl << C << endl;

    C = A.clone();
    //矩阵相加、相减
    C += A;
    cout << "C += A ->" << endl << C << endl;
    C -= A;
    cout << "C -= A ->" << endl << C << endl;

    Mat D;
    A.convertTo(D, CV_32FC1);// Only CV_32FC1, CV_32FC2, CV_64FC1 and, CV_64FC2
                             //能够被用于矩阵乘法
    cout << "D = " << endl << D << endl;
    D *= D;
    cout << "D *= ->" << endl << D << endl;

    Mat DD = A.clone();
    cout << "DD.type() = " << DD.type() << endl;
    cout << "DD = " << endl << DD << endl;
    DD.convertTo(DD, CV_64FC1);
    cout << "DD.type() = " << DD.type() << endl;
    cout << "DD = " << endl << DD << endl;

    DD *= 100;
    cout << "DD *= ->" << endl << DD << endl;
    DD.convertTo(DD, CV_8UC1);
    cout << "DD convert to CV_8UC1 ->" << endl << DD <<endl;

    //type和depth应该是一样的,表示每个像素的位数
    Mat E;
    //E = D + A;//error,runtime exception
    add(A, D, E, cv::Mat(), CV_32SC1);
    cout << "E = " << endl << DD << endl;
    cout << "E.type() =" << endl << E.type() << endl;

    B = 250;
    add(B, D, E, cv::Mat(), CV_32SC1);
    cout << "B=250 ,E = B + D with CV_32SC1 ->" << endl
         << E << endl;
    cout << "E->depth: "<< endl << E.depth()<< endl;

    cv::add(B, D, E, cv::Mat(), CV_8UC1);
    std::cout << "B = 250, E = B + D with CV_8UC1 -> " << std::endl
                  << E << std::endl << std::endl;
    cout << "E->depth: "<< endl << E.depth()<< endl;
    cout << "E->channels:"<<endl << E.channels()<<endl;

    //创建一个7*7的矩阵,类型为CV_32F,C3表示是3通道。
    //scalar是对矩阵进行初始化赋值,第一个通道为1,第二个为3,第三个为5
    Mat M(7, 7, CV_32FC3, Scalar(1, 3, 5));
    cout << "M =" << endl << M << endl;

    //3通道修改某个像素点的值,可以通过循环M的行、列修改所有的像素点值
    Vec3f pix;
    pix[0] = 2;
    pix[1] = 5;
    pix[2] = 8;
    M.at<Vec3f>(0, 0) = pix;

    //单独修改 某个像素点的某条通道,三通道0、1、2
    M.at<Vec3f>(1, 1)[1] = 10;

    cout << "M =" << endl << M << endl;
    **/

    /*图片线性叠加
    Mat srcImage1 = imread("./hehua.jpg");
    Mat srcImage2 = imread("./shuimu.jpg");
    Mat desImage;

    if(srcImage1.empty() || srcImage2.empty()){
        cout << "图像加载失败" << endl;
        return -1;
    }

    double alpha = 0.2;
    double beta = 1.0 - alpha;

    namedWindow("线性混合", WINDOW_NORMAL);
    //1图,线性混合1图权重,2图,线性混合2图权重,添加到每一个线性总和的gamma值,目标图像
    addWeighted(srcImage1, alpha, srcImage2, beta, 0.0, desImage);

    imshow("线性混合", desImage);
    namedWindow("img1", WINDOW_NORMAL);
    imshow("img1", srcImage1);
    namedWindow("img2", WINDOW_NORMAL);
    imshow("img2", srcImage2);

    waitKey(0);
    */

    /*不同大小图片的线性混合
    Mat srcImage = imread("./maomi.jpg");
    Mat addImage = imread("./hehua.jpg");
    Mat maskImage = imread("./hehua.jpg", IMREAD_GRAYSCALE);//灰度图

    if(srcImage.empty() || addImage.empty()){
        cout << "加载失败。" << endl;
        return 0;
    }
    imshow("srcImage", srcImage);
    imshow("addImage", addImage);

    //通过Rect函数设置ROI区域,可以调节图片的权重
    //出来的imageROI,按照addImage图像的大小切下来的srcImage大小。
    //Rect前两个参数表示图像的坐标,然后才是矩形的长宽(多少列就是长,多少行就是宽)
    //imageROI不是srcImage的副本,是和srcImage矩阵的头指针关联,如果修改了
    //imageROI,那么srcImage也会相应改变。所以ROI是srcImage的感兴趣区域

    //Mat imageROI = srcImage(Rect(50, 50, addImage.cols, addImage.rows));
    //addWeighted(imageROI, 0.7, addImage, 0.3, 0, imageROI);

    //以Range()函数设置ROI区域,不能调节权重
    //第一个Rang表示行采取关联的行范围,第二个Rang表示采取关联的列范围
    Mat imageROI = srcImage(Range(50, 50+maskImage.rows), Range(50, 50+maskImage.cols));
    //这里应该是把maskImage的非零元素复制给imageROI,但是addImage做了什么?
    //这里imageROI被改变,相应的srcImage的对应矩阵部分改变
    addImage.copyTo(imageROI, maskImage);

    imshow("hunhe", srcImage);
    */

    return a.exec();
}
View Code

其中每一段功能都以/** **/分隔,方便测试。

注:imwrite();这个接口,如果在pro中不分debug和release编译,直接加载所有的库文件,在debug的时候是会出错的,保存不了图片,release则没问题。所以pro中区分了编译加载。

猜你喜欢

转载自www.cnblogs.com/warmSnowFY/p/11051417.html
今日推荐