一、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 }
练习代码:
#include "widget.h" #include#include #include #include #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 (i, j); rgba[0] = UCHAR_MAX; rgba[1] = saturate_cast (float((mat.cols) - j) / ((float)mat.cols) * UCHAR_MAX); rgba[2] = saturate_cast (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 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_(3, 3) << 1,2,3,4,5,6,7,8,9); cout << "A =" << endl << A < */ /*图片线性叠加 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(); }(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 << 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:"< (0, 0) = pix; //单独修改 某个像素点的某条通道,三通道0、1、2 M.at (1, 1)[1] = 10; cout << "M =" << endl << M << endl; *
其中每一段功能都以/** **/分隔,方便测试。
注:imwrite();这个接口,如果在pro中不分debug和release编译,直接加载所有的库文件,在debug的时候是会出错的,保存不了图片,release则没问题。所以pro中区分了编译加载。