赞
踩
目录
1.1、什么是Open CV
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
1.2、优点
1.3、如何获得Open CV
2.1、工具及版本
2.2、opencv安装与环境配置
2.3、将Open CV与Visual Studio 2017关联
Visual Studio 2017新建一个C++空项目,然后点击【视图】,【其他窗口】,【属性管理器】,然后就弹出一个属性管理器窗口,如下图:
双击打开Debug | x64 文件夹下的Micrsoft.Cpp.x64.user(x86的选择Debug | Win32下的Micrsoft.Cpp.Win32.user ),在下图标注的位置添加包含目录
2.4、开始第一个项目
将窗口上的解决方案配置设置为Debug,解决方案平台设置为x64(x86系统则设置为x86)
视图选项 -> 解决方案资源管理器,或者快捷键Ctrl+Alt+L
,在源文件夹新建一个C++项目,右键源文件 -> 添加 -> 新建项 -> C++文件,书写代码测试
- #include<opencv2/opencv.hpp>
- using namespace cv;
- void main() {
- //图片1.jpg存在于项目C++文件的同一目录下
- Mat img = imread("1.jpg");
- //显示图片
- imshow("img",img);
- waitKey(0);
- }
局部效果图
可能出现的问题
3.1、头文件与命名空间
- #include "opencv2/opencv.hpp"
- using namespace cv;
3.2、imread()函数
3.3、namedWindow()函数
3.4、imshow()函数
3.5、imwrite()函数
3.6、waitKey()函数
Esc
的ASCII码为273.7、图像属性
3.8、示例程序
- #include<opencv2/opencv.hpp>
- #include <iostream>
-
- using namespace cv;
- using namespace std;
-
- void main() {
- Mat srcImg = imread("1.jpg");//读取图片
- if (!srcImg.empty()) {
- cout<< "高度:" << srcImg.rows << endl;
- cout << "宽度:" << srcImg.cols << endl;
- cout << "通道数:" << srcImg.channels() << endl;
- cout << "位深度:" << srcImg.depth() << endl;
- }
- cvtColor(srcImg,srcImg,CV_BGR2GRAY);//转化为灰度图
- namedWindow("img",WINDOW_AUTOSIZE);//创建窗口
- imshow("img",srcImg);
- imwrite("1.bmp",srcImg);
- waitKey(0);
- }
3.9、效果展示
4.1、VideoCapture类
对视频文件或摄像头进行视频读取。
4.2、VideoWriter类
对视频文件或摄像头进行视频写入磁盘。
4.3、读取视频与摄像头示例源代码
- #include<opencv2/opencv.hpp>
- using namespace cv;
-
- void main() {
- //读取视频文件,视频文件2.avi与C++文件处于同一目录
- VideoCapture cap("2.avi");
- //读取摄像头
- //VideoCapture cap(0);
- if (!cap.isOpened()) {
- return;
- }
- Mat frame;
- while (1) {
- cap >> frame;
- //Canny(frame, frame, 30, 100); //Canny边缘检测
- //cvtColor(frame, frame, CV_BGR2HSV); //颜色空间转换到HSV
- if (!frame.empty()) {
- imshow("video", frame);
- if (waitKey(30) == 27) {
- break;
- }
- }
- else
- break;
- }
- cap.release();
- }
4.3、效果展示
5.1、图像批量读取
- char filename[50];
- char winName[50];
- Mat srcImg;
- for(int i = 1; i<30; i++){
- //图片集位于E:\\pic文件夹,命名为 1.bmp、2.bmp ......
- sprintf_s(filename, "E:\\pic\\%d.bmp", i);
- sprintf_s(winName, "NO--%d", i);
- srcImg = imread(filename);
- if(srcImg.empty())
- break;
- imshow(winName, srcImg);
- }
- waitKey(0);
- destroyAllWindows();
5.2、视频分解
- Mat frame;
- char outfile[50];
- VideoCapture cap("E:\\2.avi");
- if(!cap.isOpened()) //打开失败
- return;
- int totalFrame = cap.get(CV_CAP_PROP_FRAME_COUNT); //获取视频总帧数
- for(int i = 1; i<=totalFrame; i++){
- cap>>frame;
- if(frame.empty())
- break;
- sprintf_s(outfile, "E:\\pic\\%d.bmp", i);//规律命名每一帧图片
- imwrite(outfile, frame);//图片写入磁盘文件
- imshow("video", frame);
- waitKey(15);
- }
- cap.release();
- destroyAllWindows();
5.3、多图合并
- VideoWriter writer("E:\\out.avi", -1, 20, Size(720, 576), true);
- VideoCapture cap;
- char filename[50];
- Mat frame;
- for (int i = 1; i < 400; i++){
- sprintf_s(filename, "E:\\pic\\%d.bmp", i);
- cap.open(filename);
- if (!cap.isOpened())
- break;
- cap >> frame;
- if (frame.empty())
- break;
- writer << frame;
- }
- waitKey(0);
- destroyAllWindows();
6.1、常用数据结构
6.2、Mat类基础
简介
Mat类创建
7.1、line()函数
7.2、circle()函数
7.3、rectangle()函数
7.4、ellipse()函数
7.5、fillPoly()/polylines()函数
7.6、putText()函数
7.7、示例源代码
- Mat img(300, 300, CV_8UC3, Scalar(0, 0, 0));
- line(img, Point(10, 10), Point(200, 200), Scalar(0, 255, 255), 10, 8); //画线
- circle(img, Point(150, 150), 100, Scalar(255, 255, 0), -1, 8); //画圆
- rectangle(img, Point(10, 10), Point(240, 200), Scalar(0, 0, 255), 2, 8); //画矩形
- rectangle(img, Rect(10, 10, 230, 190), Scalar(0, 0, 255), -1, 8); //填充矩形
- ellipse(img, Point(150, 150), Size(100, 50), 45, 0, 360, Scalar(0, 255, 255), -1, 8); //画椭圆
- ellipse(img, RotatedRect(Point(150, 150), Size(100, 50), 0), Scalar(0, 255, 0), 2, 8);
- Point ppt[] = { Point(120, 50), Point(180, 50), Point(210, 100), Point(180, 150), Point(120, 150), Point(90, 100) };
- const Point* pts[] = { ppt };
- int npt[] = { 6 };
- fillPoly(img, pts, npt, 1, Scalar(0, 255, 255), 8); //画填充多边形
- polylines(img, pts, npt, 1, true, Scalar(0, 154, 209), 2, 8); //画非填充多边形
- putText(img, "China", Point(100, 100), CV_FONT_HERSHEY_COMPLEX, 2, Scalar(0, 255, 255), 2, 8);//添加文字
- imshow("image",img);
- waitKey(0);
7.8、效果展示
8.1、鼠标操作
指定鼠标操作消息回调函数
原型: setMouseCallback(const string& winname,MouseCallback onMouse,void* userdata=0)
示例源代码
- #include<opencv2/opencv.hpp>
- using namespace cv;
-
- Mat img(500, 500, CV_8UC3, Scalar(255, 255, 255));
- Point pt;
-
- //鼠标回调函数,名称可变,但是参数不可变
- void onMouse(int event, int x, int y, int flag, void *param) {
- if (event == CV_EVENT_LBUTTONDOWN) {//鼠标左键按下,画出圆形
- circle(img, Point(x, y), 100, Scalar(0, 0, 255), 2, 8);
- }
- else if (event == CV_EVENT_RBUTTONDOWN) {//鼠标右键按下,记录按下点
- pt.x = x;
- pt.y = y;
- }
- else if (event == CV_EVENT_RBUTTONUP) {//鼠标右键抬起,画出矩形框
- rectangle(img,Point(pt.x, pt.y), Point(x, y), Scalar(0, 255, 255), 2, 8);
- }
- }
- void main() {
- //鼠标点击调用
- namedWindow("Mouse",WINDOW_AUTOSIZE);
- setMouseCallback("Mouse", onMouse, 0);
- while (1) {
- imshow("Mouse", img);
- if(27==waitKey(20))
- break;
- }
- }
8.2、滑动条操作
创建滑动条并指定回调函数
原型:createTrackbar(const string& trackbarname,const string& winname,int* value,int count,TrackbarCallback onChange=0,void* userdata=0)
获得滚动条当前位置
示例源代码
- #include<opencv2/opencv.hpp>
- using namespace cv;
-
- Mat srcImg = imread("1.jpg", 0);
- Mat desImg;
- int value = 20;
- //滚动条回调函数
- void onchange(int value, void *param) {
- //threshold(srcImg,desImg,value,255,THRESH_BINARY);//灰度
- Canny(srcImg, desImg, value, 255);//边缘检测
- imshow("TrackBar", desImg);
- }
- void main() {
- //滚动条
- namedWindow("TrackBar",WINDOW_AUTOSIZE);
- //threshold(srcImg, desImg, value, 255, THRESH_BINARY);
- createTrackbar("Threshlod","TrackBar",&value,255,onchange,0);
- Canny(srcImg, desImg, value, 255);//边缘检测
- imshow("TrackBar", desImg);
- waitKey(0);
- }
9.1、鼠标截图
主要功能
源程序
- #include<opencv2/opencv.hpp>
- #include<iostream>
- using namespace cv;
- using namespace std;
-
- Mat img = imread("1.jpg");
- Mat temp = img.clone();
- Mat ROI;
- bool flag1 = false;
- Point pt;
- //鼠标监测事件
- void onMouse(int event,int x,int y,int flag,void *param) {
- switch (event)
- {
- case CV_EVENT_LBUTTONDOWN:
- pt.x = x;
- pt.y = y;
- flag1 = true;
- break;
- case CV_EVENT_MOUSEMOVE:
- if (flag1) {
- temp.copyTo(img);
- rectangle(img,Point(pt.x,pt.y),Point(x,y),Scalar(0,0,255),2,8);
- }
- break;
- case CV_EVENT_LBUTTONUP:
- flag1 = false;
- temp.copyTo(img);
- ROI = img(Rect(pt.x,pt.y,abs(x - pt.x),abs(y-pt.y)));
- imshow("ROI",ROI);
- break;
- default:
- break;
- }
- }
- void main() {
- namedWindow("Mouse",WINDOW_AUTOSIZE);
- setMouseCallback("Mouse",onMouse,0);
- while (1) {
- imshow("Mouse",img);
- if (27 == waitKey(20)) {
- break;
- }
- }
- }
效果图
9.2、滑动条视频播放
主要功能
源程序
- #include<opencv2/opencv.hpp>
- #include<iostream>
- using namespace cv;
- using namespace std;
-
- int value = 20;//记录滑动块位置
- void onchange(int value,void *param) {
- VideoCapture cap = *(VideoCapture *)param;//强制转换指针类型
- cap.set(CV_CAP_PROP_POS_FRAMES,value);
- }
-
- void main() {
- VideoCapture cap("2.avi");
- int frameCount = cap.get(CV_CAP_PROP_FRAME_COUNT);//视频总帧数
- Mat frame;
- if (!cap.isOpened()) {//视频打开失败
- return;
- }
- namedWindow("video",WINDOW_AUTOSIZE);
- createTrackbar("帧数","video",&value,frameCount,onchange,&cap);
- while (1) {
- cap >> frame;
- int pos = cap.get(CV_CAP_PROP_POS_FRAMES);
- setTrackbarPos("帧数", "video", pos);
- if (frame.empty()) {
- break;
- }
- imshow("video",frame);
- if (27 == waitKey(30)) {
- break;
- }
- }
- cap.release();
- destroyAllWindows();
- }
效果图
10.1、动态地址计算访问
核心代码
- Mat img = imread("1.jpg");
- Mat dst = img.clone();//图像克隆/复制
- int rows = dst.rows;//记录图像行数
- int cols = dst.cols;//记录图像列数
- for (int i = 0; i < rows; i++) {
- for (int j = 300; j < cols; j++) {
- //彩色图像 image.at<Vec3b>(i,j)[channel] = value;
- //灰度图像 image.at<uchar>(i,j)= value;
- dst.at<Vec3b>(i, j)[0] = 0;//访问第i行第j列像素蓝色通道
- dst.at<Vec3b>(i, j)[1] = 255;//访问第i行第j列像素绿色色通道
- dst.at<Vec3b>(i, j)[2] = 0;//访问第i行第j列像素红色通道
- }
- }
10.2、指针访问
核心代码
- int rowNumber = img.rows;//行数
- int colNumber = img.cols*img.channels();//列数*通道数=每一行元素个数
- for (int i = 0; i < rowNumber; i++) {
- uchar * data = dst.ptr<uchar>(i);//获取第i列的首元素地址
- for (int j = 0; j < colNumber; j++) {
- switch (j%3){
- case 0:data[j] = 0;
- break;
- case 1:data[j] = 255;
- break;
- case 2:data[j] = 0;
- break;
- default:
- break;
- }
- }
- }
10.3、迭代器访问
核心代码
- Mat_<Vec3b>::iterator it = dst.begin<Vec3b>();//初始位置
- Mat_<Vec3b>::iterator itend = dst.end<Vec3b>();//终止位置
- for (; it != itend; ++it) {
- (*it)[0] = 0;//蓝色通道
- (*it)[1] = 255;//绿色通道
- (*it)[0] = 0;//红色通道
- }
10.4、添加减色效果
核心代码
data[j] = data[j]/64*64+20;//注意data[j]/64*64 <=data[j]
10.5、添加雪花效果
核心代码
- for(int k=0;k<4000;k++){
- int i=rand() % img.rows;
- int j=rand() % img.cols;
- dst.at<Vec3b>(i, j)[0] = 255;//访问第i行第j列像素蓝色通道
- dst.at<Vec3b>(i, j)[1] = 255;//访问第i行第j列像素绿色色通道
- dst.at<Vec3b>(i, j)[2] = 255;//访问第i行第j列像素红色通道
- }
11.1、图像加法
常用函数
示例
- Mat img1, img2;
- Mat dst;
- dst = img1 +img2;
- add(img1, img2, dst);
- addWeighted(img1, 0.5, img2, 0.5, 0, dst); //设置加的权值
11.2、图像减法
常用函数
示例
- Mat img1, img2;
- Mat dst;
- dst = img1 -img2;
- subtract(img1, img2, dst);
- absdiff(img1, img2, dst);
11.3、图像乘除法
常用函数
示例
- Mat img1, img2;
- Mat dst;
- dst = A * img1;
- dst = img1 /A;
11.4、图像逻辑运算
常用函数
示例
- bitwise_and(img1,img2,dst);//与运算
- bitwise_or(img1, img2, dst);//或运算
- bitwise_not(img1,dst);//非运算
- bitwise_xor(img1, img2, dst);//异或运算
12.1、对比度亮度调整
原理: g(x) = a * f(x) + b
示例源程序
- #include<opencv2/opencv.hpp>
- #include<iostream>
-
- using namespace std;
- using namespace cv;
-
-
- int constast_value = 20;//对比度初始值
- int bright_value = 20;//亮度初始值
-
- void onchange(int value, void *param) {
- Mat img = *(Mat *)param;
- Mat dst(img.size(),img.type());//创建跟img大小一致的图形
- int rows = img.rows;
- int cols = img.cols;
- for (int i = 0; i < rows; i++) {
- for (int j = 0; j < cols; j++) {
- //saturate_cast<uchar>()函数用于防止溢出,data<0?0:data data>255?255:data
- dst.at<Vec3b>(i, j)[0] =saturate_cast<uchar>( img.at<Vec3b>(i, j)[0] * constast_value*0.01 + bright_value);
- dst.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(img.at<Vec3b>(i, j)[1] * constast_value*0.01 + bright_value);
- dst.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(img.at<Vec3b>(i, j)[2] * constast_value*0.01 + bright_value);
- }
- }
- imshow("效果图",dst);
- }
- void main() {
- Mat img = imread("1.jpg");
- namedWindow("效果图",WINDOW_AUTOSIZE);
- createTrackbar("对比度","效果图",&constast_value,300,onchange,&img);
- createTrackbar("亮度", "效果图", &bright_value, 300, onchange, &img);
- onchange(constast_value,&img);
- onchange(bright_value, &img);
- }
12.2、通道分离与合并
通道分离:split()函数
示例程序
- void channelsSplit() {
- Mat img = imread("1.jpg");
- vector<Mat> channels;
- Mat blueChannel, greenChannel, redChannel;
- split(img,channels);
- blueChannel = channels.at(0);
- greenChannel = channels.at(1);
- redChannel = channels.at(2);
- imshow("Blue",blueChannel);
- imshow("Green",greenChannel);
- imshow("Red",redChannel);
- }
通道合并:merge()函数
示例程序
- void channelsMerge() {
- Mat img = imread("1.jpg");
- Mat mergeImg = Mat::zeros(img.size(),img.type());
- vector<Mat> channels;
- Mat blueChannel, greenChannel, redChannel;
- split(img, channels);
- blueChannel = channels.at(0);
- greenChannel = channels.at(1);
- redChannel = channels.at(2);
- //对每个通道进行二值化处理
- threshold(blueChannel,blueChannel,100,255,THRESH_BINARY);
- threshold(greenChannel, greenChannel, 100, 255, THRESH_BINARY);
- threshold(redChannel,redChannel,100,255,THRESH_BINARY);
- //进行通道合并
- merge(channels,mergeImg);
- imshow("Merge",mergeImg);
- }
13.1、感兴趣区域ROI
介绍
源程序示例
- #include <opencv2/opencv.hpp>
- using namespace cv;
-
- void main() {
- Mat img = imread("1.jpg");
- Mat ROI;
- //ROI = img(Rect(100,100,200,200));//Rect矩形区域,x,y,w,h
- ROI = img(Range(300,300+200),Range(300,300+200));//Range行列范围
- imshow("img",img);
- imshow("ROI",ROI);
- waitKey(0);
- }
13.2、ROI图像融合
简单融合:将图片添加到另一张图片上方
使用copyTo()方法
- Mat img = imread("1.jpg");
- Mat logo = imread("logo.png");
- Mat ROI = img(Rect(10,10,logo.cols,logo.rows));
- logo.copyTo(ROI);
- imshow("ROI",ROI);
- imshow("img",img);
13.3、mask掩码
特点
高级融合:去除底色,将无背景的logo添加至另一张图
- Mat img = imread("1.jpg");
- Mat logo = imread("logo.png");
- Mat mask = imread("logo.png",0);//转为灰度图
- bitwise_not(mask, mask);//图像取反操作
- threshold(mask, mask, 100, 255, THRESH_BINARY);//二值化处理
- Mat ROI;
- ROI = img(Rect(20,20,logo.cols,logo.rows));
- //logo复制到ROI位置,使用利用logo生成的掩码,相当于抠图
- logo.copyTo(ROI, mask);//使用了mask掩码操作
- imshow("ROI",ROI);
- imshow("img",img);
14.1、图像缩放
resize()函数
原型:resize(InputArray src,OutputArray dst,Size dsize,double fx=0,double fy=0,int interpolation=INTER_LINEAR);
示例代码
- ex1:
- Mat dstImg = Mat::zeros(512, 512, CV_8UC3);//建立一张512*512像素的彩色图
- Mat srcImg = imread(“1.jpg”);
- resize(srcImg, dstImg, dstImg.size());//缩放至目标图大小
-
- ex2:
- Mat dstImg ;
- Mat srcImg = imread(“1.jpg”);
- resize(srcImg, dstImg, Size(), 0.5, 0.5);//自动大小,水平与竖直方向缩放0.5
14.2、图像平移
不改变图片大小
- Mat imageTranslate(Mat &src, int xOffset, int yOffset) {
- int rows = src.rows;
- int cols = src.cols;
- Mat dst = Mat::zeros(src.size(), src.type());
- for (int i = 0; i < rows; i++) {
- for (int j = 0; j < cols; j++) {
- int x = j + xOffset;//偏移量
- int y = i + yOffset;
- if (x < cols&& y < rows &&x>=0 && y>=0) {
- dst.at<Vec3b>(y, x) = src.at<Vec3b>(i, j);
- }
- }
- }
- return dst;
- }
改变图片大小
- Mat imageTranslate(Mat &src, int xOffset, int yOffset) {
- int rows = src.rows +abs(yOffset);
- int cols = src.cols +abs(xOffset);
- Mat dst = Mat::zeros(rows,cols,src.type());
- ......
- }
14.3、图像旋转
函数getRotationMatrix2D()、warpAffine()
- void picMove() {
- Mat img = imread("1.jpg");
- Point2f center = Point2f(img.cols / 2, img.rows / 2);//中心点
- double angle = 45;//旋转角度
- double scale = 0.5;//缩放尺度
-
- Mat rotateMat;
- rotateMat = getRotationMatrix2D(center,angle,scale);
- Mat rotateImg;
- warpAffine(img, rotateImg, rotateMat, Size(1200, 1800));
- imshow("dst",rotateImg);
- }
14.4、转置和镜像
用到的函数 transpose()、flip(),可以实现转置和镜像变换,以及90°,180°旋转
- void TransposeAndFlip() {
- Mat img = imread("1.jpg");
- Mat dst;
- //transpose(img,dst);//沿主对角线翻转
- flip(img,dst,0);//flipCode = 0,沿x轴翻转,>0 沿y轴翻转,<0 水平垂直翻转
- imshow("dst",dst);
- }
15.1、方框滤波
15.2、均值滤波
15.3、高斯滤波
15.4、中值滤波
15.5、双边滤波
15.6、示例
源程序
- #include<opencv2/opencv.hpp>
- using namespace cv;
-
- void main() {
- Mat src = imread("1.jpg");
- Mat dst;
- //方框滤波
- boxFilter(src, dst, -1, Size(3, 3), Point(-1, -1), true);
- //均值滤波
- blur(src, dst, Size(5, 5));
- //高斯滤波
- GaussianBlur(src,dst,Size(5,5),1);
- //中值滤波
- medianBlur(src,dst,3);
- //双边滤波
- bilateralFilter(src,dst,5,10.0,2.0);
- imshow("dst", dst);
- waitKey(0);
- }
16.1、固定阈值
函数:threshold()
原型:double threshold(InputArray src,OutputArray dst,double thresh,double maxval,int type);
示例代码
threshold(src,dst,120,255,CV_THRESH_BINARY);//120-255的值为1,其他为0
16.2、自适应阈值
函数:adaptiveThreshold()
原型:adaptiveThreshold(InputArray src,OutputArray dst,double maxValue,int adaptiveMethod,int thresholdType,int blockSize,double C)
示例代码
- //注意src图片需要为灰度图
- adaptiveThreshold(src,dst,255,ADAPTIVE_THRESH_GAUSSIAN_C,CV_THRESH_BINARY,11,5);
16.3、进度条调节阈值
示例程序
- #include<opencv2/opencv.hpp>
- using namespace cv;
-
- int fixvalue = 20;
- int blocksize = 5;
- int c = 5;
- Mat dst;
- void onchange(int, void * param) {
- Mat src = *(Mat *)param;
- threshold(src, dst, fixvalue, 255, THRESH_BINARY);
- if (blocksize % 2 == 0)
- blocksize++;
- adaptiveThreshold(src, dst, 255, ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, blocksize, c);
- imshow("固定阈值",dst);
- imshow("自适应阈值", dst);
- }
- void main() {
- Mat img = imread("1.jpg", 0);
- namedWindow("固定阈值", WINDOW_AUTOSIZE);
- namedWindow("自适应阈值", WINDOW_AUTOSIZE);
- createTrackbar("fixvalue", "固定阈值", &fixvalue, 255, onchange, &img);
- createTrackbar("blocksize", "自适应阈值", &blocksize, 100, onchange, &img);
- createTrackbar("c", "自适应阈值", &c, 100, onchange, &img);
-
- onchange(fixvalue, &img);
- onchange(blocksize, &img);
- onchange(c, &img);
- imshow("img", img);
- waitKey(0);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。