目录
opencv学习资料声明
对于C++ 不熟悉的伙伴,强推这版学习资源!
B站学习资源:4h上手C++版Opencv
安装opencv包以及添加包含目录、库目录和附加依赖项看视频即可
以下是我的学习B站视频和知乎大神笔记整理与自己所在领域——医学图像处理相关的实践和学习笔记!
1.基础知识
1.1 Read Images Videos and Webcams
示例:
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>//输入输出流
using namespace cv;
using namespace std;
/ Images //
void main() {
string path = "Resources/test.png";
//1.读取:imread读取到Mat类型的 img中
Mat img = imread(path);
//检测image有无数据,无数据 img.empty()返回真
if (img.empty())
{
cout << "Could not open or find the image" << endl;
return -1;
}
cout << "图像的行数为: " << image1.rows << endl; //获取图像的高度,行数;
cout << "图像的列数为: " << image1.cols << endl; //获取图像的宽度,列数;
cout << "图像的通道数为: " << image1.channels() << endl; //获取图像的通道数,彩色图=3,灰度图=1;
cout << "图像的尺寸为: " << image1.size << endl; //获取图像的尺寸,行*列;
//2.保存:imwrite保存图像为png格式
imwrite("Resources/test_save.png", img);
//3.显示:imshow窗口显示图像
imshow("Image", img);
waitKey(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);
// Mat img;
//
// while (true) {
//
// cap.read(img);
// imshow("Image", img);
// waitKey(1);
// }
//}
imread读取图像的方式有三种:
① 彩色:
imread(path, IMREAD_COLOR);
or
imread(path, 1);
②灰度:
imread(path, IMREAD_GRAYSCALE);
or
imread(path, 0);
③alpha通道:
为实现图形的透明效果,采取在图形文件的处理与存储中附加上另一个8位信息的方法,这个附加的代表图形中各个素点透明度的通道信息就被叫做Alpha通道。Alpha通道使用8位二进制数,就可以表示256级灰度,即256级的透明度。
imread(path, IMREAD_UNCHANGED);
or
imread(path, -1);
1.2 Basic Functions
基本的图像处理操作(依次增加操作):
图像转换(cvtColor)
图像模糊(GaussianBlur)
图像边缘检测(Canny)
图像边缘扩大(dilate)
图像边缘侵蚀(erode)\
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
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); //BGR——GRAY
GaussianBlur(imgGray, imgBlur, Size(7, 7), 5, 0); // 高斯模糊 Size(7, 7), 5, 控制模糊程度
Canny(imgBlur, imgCanny, 25,75); // 边缘检测,使用前常进行模糊处理 ,75 控制边缘数(越大边缘越少)
//Q:边缘检测后部分边缘没有被完全填充
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);
}
imshow图像展示:
1.3 Resize and Crop
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
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); //可按比例resize,也可以给实际的数字
Rect roi(200, 100, 300, 300); //矩形数据类型 rectangle,定位左上角的点,并给出矩形size
imgCrop = img(roi);
imshow("Image", img);
imshow("Image Resize", imgResize);
imshow("Image Crop", imgCrop);
waitKey(0);
}
1.4 Draw Shapes and Text
圆(circle)
框(rectangle)
线(line)
显示内容(putText)\
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
// Draw Shapes and Text //
void main() {
// Blank Image
Mat img(512, 512, CV_8UC3, Scalar(255, 255, 255));
circle(img, Point(256, 256), 155, Scalar(0, 69, 255),FILLED); //Point表示圆心;155表示圆的半径; FILLED填满,数字表示线的粗细
rectangle(img, Point(130, 226), Point(382, 286), Scalar(255, 255, 255), FILLED); //定义左上角和右下角
line(img, Point(130, 296), Point(382, 296), Scalar(255, 255, 255), 2);
putText(img, "Murtaza's Workshop", Point(137, 262), FONT_HERSHEY_DUPLEX, 0.75, Scalar(0, 69, 255),2);//0.75字体大小,2字体粗细
imshow("Image", img);
waitKey(0);
}
1.5 Warp Images
透视转换
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
/// Warp Images //
void main() {
string path = "Resources/cards.jpg";
Mat img = imread(path);
Mat matrix, imgWarp;
float w = 250, h = 350; // 目标转换大小
Point2f src[4] = { {529,142},{771,190},{405,395},{674,457} }; //定位目标点
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));
for (int i = 0; i < 4; i++)
{
circle(img, src[i], 10, Scalar(0, 0, 255), FILLED);
} //实心圆圈注释四个角
imshow("Image", img);
imshow("Image Warp", imgWarp);
waitKey(0);
}
1.6 Color Detection
图像转换为HSV空间,更容易查找颜色
创建色调可调节滑动窗口
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
/// Color Detection //
void main() {
string path = "Resources/lambo.png";
Mat img = imread(path);
Mat imgHSV, mask;
int hmin = 0, smin = 110, vmin = 153;
int hmax = 19, smax = 240, vmax = 255;
cvtColor(img, imgHSV, COLOR_BGR2HSV);
namedWindow("Trackbars", (640, 200));
createTrackbar("Hue Min", "Trackbars", &hmin, 179);
createTrackbar("Hue Max", "Trackbars", &hmax, 179);
createTrackbar("Sat Min", "Trackbars", &smin, 255);
createTrackbar("Sat Max", "Trackbars", &smax, 255);
createTrackbar("Val Min", "Trackbars", &vmin, 255);
createTrackbar("Val Max", "Trackbars", &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(1);
}
}
1.7 Shape/Contour Detection
使用颜色进行对象检测和跟踪
存在问题:图像在放大后像素间存在间隙(为什么在1.2小节中进行膨胀的原因)
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
/// Color Detection //
void getContours(Mat imgDil, Mat img) {
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
//drawContours(img, contours, -1, Scalar(255, 0, 255), 2);
//扩张,轮廓,层次,方法
vector<vector<Point>> conPoly(contours.size());
vector<Rect> 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(conPoly[i]);
int objCor = (int)conPoly[i].size();
if (objCor == 3) { objectType = "Tri"; }
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 = "Rect";}
}
else if (objCor > 4) { objectType = "Circle"; }
drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);
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), 2);
}
}
}
void main() {
string path = "Resources/shapes.png";
Mat img = imread(path);
Mat imgGray, imgBlur, imgCanny, imgDil, imgErode;
// Preprocessing
cvtColor(img, imgGray, COLOR_BGR2GRAY);
GaussianBlur(imgGray, imgBlur, Size(3, 3), 3, 0);
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 Dil", imgDil);
waitKey(0);
}