课程来源:哔哩哔哩
环境:OpenCV4.5.1 + VS2019
目录
准备工作:“Resources"文件
第一章:读图、读视频和网络摄像机
第二章:基本职能(灰度,模糊,边缘检测,膨胀,图像腐蚀)
第三章:调整大小和裁剪图像
第四章:绘制形状和文本
第五章:扭曲视角(透视变换)
第六章:颜色检测
第七章:形状/轮廓检测(边缘检测)
“Resources"文件下载链接:
https://pan.baidu.com/s/1uzVDwl8lD2qVTY1bFlhF1A
提取码:5n48
#include
#include
#include
#include
//第一章:读图、读视频和网络摄像机
using namespace cv;
using namespace std;
// Image //
void main() {
string path = "Resources/test.png";
Mat img = imread(path);
imshow("Image", img);
waitKey(0); //写0为无穷大
}
Video //
//
//void main() {
//
// string path = "Resources/test_video.mp4";
// VideoCapture cap(path);
// Mat img;
//
// while (true) {
//
// cap.read(img);
//
// imshow("Image", img);
// waitKey(20);
//
// }
//
//}
// Webcam //
//
//void main() {
//
// VideoCapture cap(0); //若多个摄像头则填1
// Mat img;
//
// while (true) {
//
// cap.read(img);
//
// imshow("Image", img);
// waitKey(1);
//
// }
//
//}
#include
#include
#include
#include
//第二章:基本职能(灰度,模糊,边缘检测,膨胀,图像腐蚀)
using namespace cv;
using namespace std;
// Basic Functions //
void main() {
string path = "Resources/test.png";
Mat img = imread(path);
Mat imgGray, imgBlur, imgCanny, imgDil, imgErode;
cvtColor(img, imgGray, COLOR_BGR2GRAY); //灰度
GaussianBlur(imgGray, imgBlur, Size(3, 3), 3, 0); //模糊(参数四和五:sigmaX 和 sigmaY
Canny(imgBlur, imgCanny, 25, 75); //边缘检测(参数四和五:两个阈值
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); //返回指定形状和尺寸的结构元素(参数一:指定形状(这里为矩形);参数二指定尺寸
dilate(imgCanny, imgDil, kernel); //膨胀(参数三:膨胀内核
erode(imgDil, imgErode, kernel); //图像腐蚀(参数三:腐蚀内核
imshow("Image", img);
imshow("Image Gray", imgGray);
imshow("Image Blur", imgBlur);
imshow("Image Canny", imgCanny);
imshow("Image Dilation", imgDil);
imshow("Image Erode", imgErode);
waitKey(0); //写0为无穷大
}
#include
#include
#include
#include
//第三章:调整大小和裁剪图像
using namespace cv;
using namespace std;
// Resize and Crop //
void main() {
string path = "Resources/test.png";
Mat img = imread(path);
Mat imgResize, imgCrop;
cout << img.size() << endl;
resize(img, imgResize, Size(), 0.5, 0.5); //调整大小
cout << imgResize.size() << endl;
Rect roi(200, 80, 300, 300); //需要提取的矩形区域数据
imgCrop = img(roi); //需要提取的区域放于imgCrop
imshow("Image", img);
imshow("Image Resize", imgResize);
imshow("Image Crop", imgCrop);
waitKey(0); //写0为无穷大
}
#include
#include
#include
#include
//第四章:绘制形状和文本
using namespace cv;
using namespace std;
// Draw Shapes and Text //
void main() {
// Blank Image
cv::Mat img(512, 512, CV_8UC3, cv::Scalar(255, 255, 255));
circle(img, cv::Point(256, 256), 155, cv::Scalar(0, 69, 255), FILLED); //圆 (FILLED 表示填充
rectangle(img, cv::Point(130, 226), cv::Point(382, 286), cv::Scalar(255, 255, 255), FILLED); //矩形
line(img, cv::Point(130, 296), cv::Point(382, 296), cv::Scalar(255, 255, 255), 2); //直线段
// 绘制文本(参数四:字体; 参数五:比例; 参数七:厚度
putText(img, "Murtaza's Workshop", Point(137, 262), FONT_HERSHEY_DUPLEX, 0.75, Scalar(0, 69, 255), 2);
int ccc = 7;
cv::putText(canvas, to_string(ccc), cv::Point(top.x - 20, top.y - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);
cv::putText(canvas, "width=" + to_string(width), cv::Point(top.x + 120, top.y - 165), cv::FONT_HERSHEY_COMPLEX, 1.25, cv::Scalar(255, 135, 160), 2);
cv::imshow("Image", img);
cv::waitKey(0); //写0为无穷大
}
#include
#include
#include
#include
//第五章:扭曲视角(透视变换)
using namespace cv;
using namespace std;
// Warp Image //
float w = 250, h = 350; //扭曲后的宽高
Mat matrix, imgWarp;
void main() {
string path = "Resources/cards.jpg";
Mat img = imread(path);
Point2f src[4] = { {529,142},{771,190},{405,395},{674,457} }; //扭曲前的四个点坐标(顺序为Z)
Point2f dst[4] = { {0.0f,0.0f},{w,0.0f},{0.0f,h},{w,h} }; // 后
matrix = getPerspectiveTransform(src, dst); //获取 透视变换矩阵
warpPerspective(img, imgWarp, matrix, Point(w, h)); //透视变换(参数三:透视变换矩阵M;参数四:输出矩阵的尺寸)
在原图中用红点标记四个角
//for (int i = 0; i < 4; i++) {
// //circle(img, Point(src[i]), 10, Scalar(0, 0, 255), FILLED);
// circle(img, src[i], 10, Scalar(0, 0, 255), FILLED);
//}
imshow("Image", img);
imshow("Image Warp", imgWarp);
waitKey(0); //写0为无穷大
}
#include
#include
#include
#include
//第六章:颜色检测
using namespace cv;
using namespace std;
// Color Detection //
Mat imgHSV, mask;
int hmin = 0, smin = 0, vmin = 0;
int hmax = 179, smax = 255, vmax = 255;
void main() {
string path = "Resources/shapes.png";
Mat img = imread(path);
cvtColor(img, imgHSV, COLOR_BGR2HSV);
namedWindow("Trackbar", (640,200));
createTrackbar("Hue Min", "Trackbar", &hmin, 179); //参数三:初始值(当前值);
createTrackbar("Hue Max", "Trackbar", &hmax, 179); //参数四:最大范围值
createTrackbar("Sat Min", "Trackbar", &smin, 255);
createTrackbar("Sat Max", "Trackbar", &smax, 255);
createTrackbar("Val Min", "Trackbar", &vmin, 255);
createTrackbar("Val Max", "Trackbar", &vmax, 255);
while (true) {
Scalar lower(hmin, smin, vmin);
Scalar upper(hmax, smax, vmax);
inRange(imgHSV, lower, upper, mask);
imshow("Image", img);
imshow("Image HSV", imgHSV);
imshow("Image Mask", mask);
waitKey(0); //写0为无穷大
}
}
#include
#include
#include
#include
//第七章:形状/轮廓检测(边缘检测)
using namespace cv;
using namespace std;
// Shapes/Contour Detection //
Mat imgGray, imgBlur, imgCanny, imgDil;
void getContours(Mat imgDil, Mat img) {
vector> contours; //轮廓组
vector hierarchy; // 向量内每个元素包含了4个int型的 向量
//hierarchy每个元素包括在四个元素代表(分别表示第i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号)
findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); //检测轮廓
// 参数二:输入的轮廓组 参数三:画第几条轮廓(-1为负数表示全画) 参数五:线宽
// 参数四:检测轮廓的方法(这里是只检测外轮廓)) 参数五:表示一条轮廓的方法(这里是只存储水平,垂直,对角直线的起始点)
//drawContours(img, contours, -1, Scalar(255, 0, 255), 2); //画出轮廓
vector> conPoly(contours.size());
vector boundRect(contours.size());
for (int i = 0; i < contours.size(); i++)
{
int area = contourArea(contours[i]); //轮廓面积
cout << area << endl;
string objectType;
// 通过面积大小过滤(去噪)
if (area > 1000)
{
float peri = arcLength(contours[i], true); //弧长(轮廓周长) (参数一:图像轮廓;参数二:是否闭合)
approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true); //对图像轮廓点 进行 多边形拟合
//参数一/二:输入/输出的点集 参数三:指定精度 参数四:是否闭合
cout << conPoly[i].size() << endl;
boundRect[i] = boundingRect(contours[i]); //计算轮廓的 垂直边界最小矩形
int objCor = conPoly[i].size(); //轮廓的角数
if (objCor == 3) { objectType = "Triangle"; }
else if (objCor == 4) {
float aspRatio = (float)boundRect[i].width / (float)boundRect[i].height; //矩形的长宽比
cout << aspRatio << endl;
if (aspRatio > 0.95 && aspRatio < 1.05) { objectType = "Square"; }
else { objectType = "Rectangle"; }
}
else if (objCor > 4) { objectType = "Circle"; };
drawContours(img, conPoly, i, Scalar(255, 0, 255), 2); //画出轮廓
// 参数二:输入的轮廓组 参数三:画第i条轮廓(负数表示全画) 参数五:线宽
rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);
putText(img, objectType, { boundRect[i].x,boundRect[i].y - 5 }, FONT_HERSHEY_PLAIN , 1, Scalar(0, 69, 255), 1);
}
cout << endl;
}
}
void main() {
string path = "Resources/shapes.png";
Mat img = imread(path);
// Preprocessing 图像预处理
cvtColor(img, imgGray, COLOR_BGR2GRAY); //灰度
GaussianBlur(imgGray, imgBlur, Size(3, 3), 3, 0); //模糊(参数四和五:sigmaX 和 sigmaY
Canny(imgBlur, imgCanny, 25, 75); //边缘检测(参数四和五:两个阈值
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); //返回指定形状和尺寸的结构元素(参数一:指定形状(这里为矩形);参数二指定尺寸
dilate(imgCanny, imgDil, kernel); //膨胀(参数三:膨胀内核
//原来的边缘线宽太细,会有间隙。所以需要进行膨胀操作
getContours(imgDil, img);
imshow("Image", img);
//imshow("Image Gray", imgGray);
//imshow("Image Blur", imgBlur);
//imshow("Image Canny", imgCanny);
//imshow("Image Dilation", imgDil);
waitKey(0); //写0为无穷大
}