课程链接:
https://www.bilibili.com/video/BV11A411T7rL/?spm_id_from=333.788
配置环境变量: 本文将opencv放在了以下路径中:
G:\github_code\rep\opencv\build\x64\vc15\bin
重启计算机
工程配置
- vc++ 目录:
包含目录:G:\github_code\rep\opencv\build\include
库目录:G:\github_code\rep\opencv\build\x64\vc15\lib
- 链接器:
输入:附加依赖项 opencv_world455d.lib (版本号从
G:\github_code\rep\opencv\build\x64\vc15\bin 可以看到)
VC++ directories:
#include
#include
#include
#include
using namespace cv;
using namespace std;
//Images
int main() {
string path = "Resources/test.jpg";
Mat img = imread(path);//由Opencv 引入的矩阵数据类型
imshow("Image", img);
waitKey(0); // 0 :指等待事件无穷大(infinite),这样打开的图片就不会关闭
return 0;
}
代码能够成功运行,显示图片,说明环境配置正确
对于图片:由opencv引入的矩阵类型 Mat 来进行读取
对于视频:是由一系列的图片组成的,需要使用while循环读取所有的img
对于摄像头:与读取视频的方式一致,区别在于路径获取 为摄像头的编号VideoCapture cap(0);
如果只有一个摄像头,通常设置为ID=0 ,如果有多个摄像头,注意修改ID的值
#include
#include
#include
#include
using namespace cv;
using namespace std;
//----------------------------------------------------------------------//
//Images
int main() {
string path = "Resources/test.jpg";
Mat img = imread(path); //由Opencv 引入的矩阵数据类型
imshow("Image", img);
waitKey(0);
return 0;
}
//----------------------------------------------------------------------//
//video
int main() {
string path = "Resources/test_video.mp4"; //视频的位置
//读取视频
VideoCapture cap(path);
Mat img;
//显示视频
while (true) {
cap.read(img);
imshow("Image", img);
waitKey(20); //等待时间20ms
}
return 0;
}
//----------------------------------------------------------------------//
//摄像头
int main() {
//读取视频
VideoCapture cap(0);
Mat img;
//显示视频
while (true) {
cap.read(img);
imshow("Image", img);
waitKey(1); //等待时间1ms
}
return 0;
}
使用函数 cvtColor(src,dst,code_color,dstCn)
函数说明:将图片从一个色域转换成另一个色域。注意OpenCV的默认颜色格式是BGR而不是RGB。 code_color 可以从 ColorConversionCodes 中查看。dstCn:目标图片的通道数,如果为0,通道数自动从 src 和 code 派生
高斯模糊 : GaussianBlur(src,dst,Size(),x,y)
边缘检测:canny
腐蚀erode()膨胀dilate()
c++ 中没有 numpy,因此使用getStructuringElement
为erode和dilate创建kernal
#include
#include
#include
#include
using namespace cv;
using namespace std;
//Images
int main() {
string path = "Resources/test.jpg";
Mat img = imread(path);
Mat dst_img, gauss_img, canny_img,dilate_img,erode_img;
//颜色转换
cvtColor(img, dst_img, ColorConversionCodes::COLOR_BGR2GRAY);
//高斯模糊
GaussianBlur(img, gauss_img, Size(7, 7), 3, 0);
//边缘检测 canny
Canny(gauss_img, canny_img, 50, 150);//threashold1,2 自己设定 ,可以使用拖拽栏来调节参数,从而设置这两个阈值,找到最佳检测
//腐蚀erode()和膨胀dilate()
//c++ 中没有 numpy,因此使用如下方式创建kernal,为dilate() 使用
Mat kernal = getStructuringElement(MORPH_RECT, Size(3, 3));
//膨胀
dilate(canny_img, dilate_img, kernal);
//腐蚀
erode(canny_img, erode_img, kernal);
imshow("Image", erode_img);
waitKey(0);
return 0;
}
resize
int main() {
string path = "Resources/test.jpg";
Mat img = imread(path);
Mat imgResize;
cout << img.size() << endl; //查看当前图片的大小 ,显示为 [640*480]
//修改图片的大小为指定的宽和高
resize(img, imgResize, Size(320, 240));
//按照比例进行缩小
resize(img, imgResize, Size(), 0.5, 0.5);
imshow("img", img);
imshow("Image", imgResize);
waitKey(0);
return 0;
}
裁剪: ROI
对于object 对其进行修剪以找到ROI (感兴趣区域)
int main() {
string path = "Resources/test.jpg";
Mat img = imread(path);
Mat imgCrop;
Rect roi(100, 100, 300, 250); //定义了一个矩形的ROI,x,y, width,height
imgCrop = img(roi);//将roi 放到img()中,从而裁剪出一个新的图片
imshow("img", imgCrop);
waitKey(0);
return 0;
}
学习如何在图片上画 矩形、圆形,添加文本的操作
int main() {
//Blank Image
//Mat img(512, 512, CV_8UC3,Scalar(255,0,0)); //创建图片:0-255 (2^8 unsigned) ,3通道(C3)的图片,Scalar(255,0,0):分别代表BGR三个颜色
Mat img(512, 512, CV_8UC3, Scalar(255, 255, 255));//创建白色的图片
//在图片上绘制一个圆形,输入圆心、半径
circle(img, Point(256, 256), 155, Scalar(0, 69, 255), FILLED); //FILLED 指填充颜色
//在图片上绘制一个蓝色的矩形,输入矩形的左上角点,右下角点,颜色和线条粗细
rectangle(img, Point(130, 266), Point(382, 286), Scalar(255, 0, 0), 2);
//在圆形上面画一条线
line(img, Point(130, 296), Point(382, 296), Scalar(255, 255, 255), 2);
//text:
putText(img, "Elio", Point(137, 262),FONT_HERSHEY_COMPLEX,0.75,Scalar(0,255,255));
imshow("img",img);
waitKey(0);
return 0;
}
在windows自带的绘图软件中打开img,在该软件的下部能够显示出图片相应点的坐标
#include
#include
#include
using namespace cv;
using namespace std;
int main() {
//读取图片
Mat img,imgdst;
string path = "Resources/card.jpg";
img = imread(path);
//设置需要变换的区域,src的四个点均为float,使用Point2f 创建
Point2f src[4] = { {216,48},{349,25},{254,183},{416,156} };//添加扑克牌的四个点
//设置扑克的宽度和长度
float width = sqrtf(pow(src[1].x - src[0].x, 2) + pow(src[1].y - src[0].y, 2));
float height = sqrtf(pow(src[1].x - src[2].x, 2) + pow(src[1].y - src[2].y, 2));
cout << "宽度: " << width << " 高度:" << height << endl;
//设置目标图片的显示坐标,注意dst和src的坐标顺序要一一对应
Point2f dst[4] = { {0.0f,0.0f},{width,0.0f},{0.0f,height},{width,height} };
//进行透视变换
Mat matrix;
matrix = getPerspectiveTransform(src, dst);
warpPerspective(img, imgdst, matrix, Point(width, height));
for(int i=0;i<4,i++){ //圈出待测区域的四个点
circle(img,src[i],10,Scalar(0,0,255),FILLED);
}
imshow("image", img);
imshow("目标图片", imgdst);
waitKey(0);
return 0;
}
效果如下:
原图:(坐标点是自己找的)
效果图:
需要将图片转换为HSV space因为在HSV 中查找颜色更加容易,cvtColor(img,imgHSV,COLOR_BGR2HSV)
选择需要的颜色inRange(imgHSV,lower,upper,mask)
颜色通常设置成一个范围,例如红色可以选择从深红到浅红,因为阴影光线等会造成颜色的误差。输出是一个mask (Mat)
颜色都是用 Scalar(B,G,R)
来定义
如何找到需要的颜色范围?
创建一个跟踪栏(track bar),opencv 中具有内置的功能,跟踪栏需要写在while 循环中
namedWindow("名称",(大小x,y))
#include
#include
#include
#include
#include
using namespace cv;
using namespace std;
int main() {
//读取图片
string path = "Resources/color.jpg";
Mat img;
img = imread(path);
//1. 将图片转成HSV
Mat imgHSV;
cvtColor(img, imgHSV, COLOR_BGR2HSV);
//2. 绘制颜色选择框窗口
int hmin=0, hmax = 0, smin = 0, smax = 0, vmin = 0, vmax = 0;
namedWindow("颜色选择", (640, 200)); //窗口名称,窗口大小
createTrackbar("Hue Min", "颜色选择", &hmin, 179);//179:h的最大范围
createTrackbar("Hue Max", "颜色选择", &hmax, 179);
createTrackbar("Sat Min", "颜色选择", &smin, 255);
createTrackbar("Sat Max", "颜色选择", &smax, 255);
createTrackbar("Val Min", "颜色选择", &vmin, 255);
createTrackbar("Val Max", "颜色选择", &vmax, 255);
Mat mask;
//绘制mask, 注意waitKey(1) ,将显示的内容放到while循环中,可以实时变化
while (true) {
Scalar lower(hmin, smin, vmin); //设置lower值
Scalar upper(hmax, smax, vmax);//设置upper值
inRange(imgHSV, lower, upper, mask);
imshow("img", img);
imshow("HSV", imgHSV);
imshow("mask", mask);
waitKey(1);
}
return 0;
}
显示效果如下:通过拖拽可以识别出不同的颜色。