了解 通道(channels)
一张彩色图片一般由三个通道组成
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main()
{
Mat rsv;
rsv = imread("C:/Users/Alaso/Desktop/1.jpg");
int channels1 = rsv.channels();
cout << channels1 << "\n";
return 0;
}
了解掩膜操作(AKA 抠图操作)
原理:
掩膜图像就是二进制图像,然后再用原图与掩膜图像进行与运算,最终得到截图
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main()
{
Mat src,dd;
src = imread("C:/Users/Alaso/Desktop/1.jpg");
if (!src.data)
{
cout << "NO Entry" << "\n";
return -1;
}
//namedWindow("Input image",CV_WINDOW_AUTOSIZE);
imshow("image", src);
dd.create(src.size(),src.type());
int iHeight = src.rows;
int iwitdth = src.cols;
int iChannels = src.channels();
for (int i = 0; i < iHeight; i++)
{
for (int j = 0; j < iwitdth; j++)
{
if (iChannels == 1)
{
int iGray = src.at<uchar>(i, j);
dd.at<uchar>(i, j) = 255 - iGray;
}
else
{
int BB = src.at<Vec3b>(i, j)[0];
int GG = src.at<Vec3b>(i, j)[1];
int RR = src.at<Vec3b>(i, j)[2];
dd.at<Vec3b>(i, j)[0] = 255 - BB;
dd.at<Vec3b>(i, j)[0] = 255 - GG;
dd.at<Vec3b>(i, j)[0] = 255 - RR;
}
}
}
namedWindow("测试输出");
imshow("测试输出", dd);
waitKey(0);
return 0;
}
Mat输入输出矩阵
先零帧起手来一个矩阵
PS:如果矩阵的数据类型不是 CV_8U(即无符号8位整数),imshow 可能无法正确显示内容
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat rsv = (Mat_<int>(3,3)<< 1,2,3,4,5,6,7,8,9);
Mat dd = (Mat_<int>(3,3) << 1, 1, 1, 1,1,1,1,1,1);
Mat ll = rsv + dd;
cout << ll << "\n";
ll.convertTo(ll,CV_8U);
waitKey(0);
return 0;
}
常见图形玩法
点
提要点:点其实就是一个圆心
Point p(3, 4);
cout << p.x << " " << p.y<<"\n";
矩形
提要点:矩形的参数可以是 1.两点 2.一个点+宽和高(point(x,y),width,height)
Rect r1(1, 2, 5, 8);//注意这个前面两个参数是左上角坐标,后面两个参数表示宽和高
cout << r1.x << " " << r1.y << " " << r1.width << " " << r1.height;
通道分离玩法
提要点:若需要将图片大小缩放,需要用**resize()**函数处理
#include<iostream>
#include<vector>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src;
src = imread("C:/Users/Alaso/Desktop/12.png");
if (src.empty())
{
cout << "No entry" << "\n";
return -1;
}
Mat tiaozhenghoudaxiao;
resize(src, tiaozhenghoudaxiao, Size(), 0.5, 0.5, INTER_LINEAR);
vector<Mat> dddd;
split(tiaozhenghoudaxiao,dddd);
Mat BB = dddd.at(0);
Mat GG = dddd.at(1);
Mat RR = dddd.at(2);
imshow("红色", BB);
imshow("绿色", GG);
imshow("蓝色", RR);
waitKey(0);
return 0;
}
颜色转换玩法
#include<iostream>
#include<vector>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src;
src = imread("C:/Users/Alaso/Desktop/12.png");
if (src.empty())
{
cout << "No entry" << "\n";
return -1;
}
Mat tiaozhenghoudaxiao,dddd1,dddd2,dddd3;
resize(src, tiaozhenghoudaxiao, Size(), 0.5, 0.5, INTER_LINEAR);
cvtColor(tiaozhenghoudaxiao,dddd1,COLOR_BGR2GRAY);
cvtColor(tiaozhenghoudaxiao, dddd2, COLOR_BGR2HSV);
cvtColor(tiaozhenghoudaxiao, dddd3, COLOR_BGR2HLS);
imshow("灰度图", dddd1);
imshow("HSV图", dddd2);
imshow("HLS图", dddd3);
waitKey(0);
return 0;
}
模糊图像处理
提要点: **GaussianBlur()**函数处理模糊图像
PS:GaussianBlur()内核大小为奇数,偶数会报错
Mat rsv,rsv2;
rsv = imread("C:/Users/Alaso/Desktop/1.jpg");
GaussianBlur(rsv, rsv2, Size(3, 3), 5, 5);
imshow("模糊图像", rsv2);
waitKey(0);
canny检测
由上的模糊处理可得有时候你的模糊图像用人眼去对比你的原图像根本看不出来一点差,由此可以引出 canny检测
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat rsv,adjust1,adjust2,mohu,yuantu;
rsv = imread("C:/Users/Alaso/Desktop/1.jpg");
resize(rsv, yuantu, Size(), 0.5, 0.5);
resize(rsv, adjust1, Size(), 0.5, 0.5);
resize(rsv, adjust2, Size(), 0.5, 0.5);
GaussianBlur(adjust1, mohu, Size(3, 3), 5, 5);
//canny检测
Canny(mohu, adjust2, 50, 150);
imshow("原图", yuantu);
imshow("模糊图像", mohu);
imshow("原图canny", rsv);
imshow("imagecanny", adjust2);
waitKey(0);
return 0;
}
截图操作
提要点:
其实就是用矩形ROI框住你想要截取的对象
注意:ROI包含四个参数,前面两个表示点坐标,后两个表示沿着x,y轴向前走的宽度和高度
#include<iostream>
#include<string>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
string path = "C:/Users/Alaso/Desktop/1.jpg";
Mat rsv = imread(path);
Mat adjust1,adjust2;
resize(rsv, adjust1, Size(), 0.5, 0.5);
Rect roi(100, 100, 300, 250);
adjust2 = adjust1(roi);
imshow("原图", adjust1);
imshow("裁剪图", adjust2);
waitKey(0);
return 0;
}
绘制图形
提要点:
主要是圆形,矩阵,直线绘制,再加上一点写文本放图像上
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat rsv(512, 512, CV_8UC3,Scalar(255,0,0));
circle(rsv, Point(256, 256), 155, Scalar(0, 255, 0), 10);
rectangle(rsv, Point(130, 226), Point(389, 245), Scalar(0, 0, 255),100);
line(rsv, Point(130, 233), Point(399, 120), Scalar(0, 255, 255),202);
putText(rsv, "Alaso_shuang", Point(137, 266), FONT_HERSHEY_COMPLEX,0.75,Scalar(0,222,222),2);
imshow("image", rsv);
waitKey(0);
return 0;
}
透视变换
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
float w = 250, h = 350;
Mat matrix,img;
int main()
{
//没错,要写透视变换了!
string path = "C:/Users/Alaso/Desktop/2.png";
Mat rsv,adjust1;
rsv = imread(path);
resize(rsv, adjust1, Size(), 0.5, 0.5);
imshow("原图", adjust1);
Point2f src[4] = { { 69,350 }, { 374,303 }, { 101,697 }, { 449,625 } };
Point2f dst[4] = { { 0.0f,0.0f }, {w ,0.0f }, { 0.0f,h }, { w,h } };
matrix = getPerspectiveTransform(src, dst);
warpPerspective(rsv, img, matrix, Point(w, h));
//for (int i = 0; i < 4; i++)
//{
//circle(adjust1,src[i],10, Scalar(0, 255, 255),10);
//}
imshow("原图", adjust1);
imshow("透视变换", img);
waitKey(0);
return 0;
}
效果是这样的
颜色提取
运用inRange()函数提取域值,产生二值化操作,即可对我们所需要的图片颜色进行提取
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int hmin = 0, smin = 110,vmin = 150;
int hmax =20, smax =240, vmax = 250;
int main()
{
string path = "C:/Users/Alaso/Desktop/3.jpg";
Mat uu = imread(path);
Mat adjust1,uu1,range_photo;
resize(uu, adjust1, Size(), 0.3, 0.3);
cvtColor(adjust1, uu1, COLOR_BGR2HSV);//为了方便颜色识别转成HSV图
namedWindow("轨迹跟踪", (630, 200));
createTrackbar("hmin","轨迹跟踪", &hmin, 179);
createTrackbar("hmax", "轨迹跟踪", &hmax, 179);
createTrackbar("smin", "轨迹跟踪", &smin, 179);
createTrackbar("smax", "轨迹跟踪", &smax, 255);
createTrackbar("vmin", "轨迹跟踪", &vmin, 255);
createTrackbar("vmax", "轨迹跟踪", &vmax, 255);
while (1)
{
Scalar lower(hmin, smin, vmin);
Scalar height(hmax, smax, vmax);
inRange(adjust1, lower, height, range_photo);
imshow("原图", adjust1);
imshow("HSV图", uu1);
imshow("HSV处理图", range_photo);
waitKey(1);
}
return 0;
}
效果是这样的
图形轮廓实现
轮廓实现其实就是先转换灰图,再用高斯模糊,然后搭配canny绘制成线条,然后再用膨胀dilate得到拟合线条,然后用这个**dilate()**搭配 findContours()(本质:在二值图像中寻找轮廓)圈出轮廓
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
void lunkuo(Mat img_dilate,Mat img)
{
vector<vector<Point>> contours;
vector<Vec4i> hh;
findContours(img_dilate, contours, hh, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
drawContours(img, contours, -1, Scalar(255, 0, 255), 2);
}
int main()
{
string path = "C:/Users/Alaso/Desktop/3.jpg";
Mat rsv = imread(path);
Mat adjust1;
Mat imgGray,mohu_photo,canny_photo,dilate_photo,erode_photo;
resize(rsv, adjust1, Size(), 0.3, 0.3);
cvtColor(adjust1, imgGray, COLOR_BGR2GRAY);
GaussianBlur(imgGray, mohu_photo, Size(3, 3), 3, 0);
Canny(mohu_photo, canny_photo, 25, 75);
Mat kennel = getStructuringElement(MORPH_RECT, Size(3, 3));
dilate(canny_photo, dilate_photo, kennel);
erode(canny_photo, erode_photo, kennel);
lunkuo(dilate_photo,adjust1);//第一个参数表示我们用dilate操作过的图像去执行下一步操作,第二个参数表示我们需要绘制怎么样的图像
imshow("原图", adjust1);
/*imshow("灰图", imgGray);
imshow("模糊图", mohu_photo);
imshow("canny图", canny_photo);
imshow("dilate图", dilate_photo);*/
waitKey(0);
return 0;
}
效果是这样的
截取图像(识别人脸)
提要点:在CascadeClassifier FaceC; 中只是声明了一个分类器对象,但没有加载具体的分类器文件。OpenCV 提供了多种预训练的 Haar 级联分类器文件,例如 haarcascade_frontalface_default.xml,你需要指定正确的路径加载它
#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/objdetect.hpp>
using namespace std;
using namespace cv;
int main()
{
string path = "C:/Users/Alaso/Desktop/1.jpg";
Mat csv = imread(path);
Mat adjust1;
resize(csv, adjust1, Size(), 0.3, 0.3);
CascadeClassifier FaceC;
FaceC.load("D:/openCV/opencv/build/etc/haarcascades/haarcascade_frontalface_default.xml");
if (FaceC.empty())cout << "No entry" << "\n";
vector<Rect> faces;
FaceC.detectMultiScale(adjust1, faces, 1.1, 1);
for (int i = 0; i < faces.size(); i++)
{
rectangle(adjust1, faces[i].tl(),faces[i].br(), Scalar(0, 255, 255), 2);
//tl() 是 "top-left" 的缩写,表示人脸区域的左上角坐标
//br() 是 "bottom-right" 的缩写,表示人脸区域的右下角坐标
}
imshow("原图", adjust1);
waitKey(0);
}
视频跟踪颜色轨迹
给定一个颜色阈值,然后存到vector中不断循环取值
#define _CRT_SECURE_NO_WARNINGS
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
using namespace cv;
using namespace std;
//vector<vector<int>> Color{ {124,48,117,143,170,255},{68,72,156,102,126,255} };//分别是紫色,绿色
vector<vector<int>> Color = { {68,72,156,102,126,255}};
vector<Scalar> mycolor = { {0, 255, 0} };
void findColor(Mat img)
{
Mat imgHSV;
cvtColor(img, imgHSV, COLOR_BGR2HLS);
for (int i = 0; i < mycolor.size(); i++)
{
Mat mask;
Scalar lower(Color[i][0], Color[i][1], Color[i][2]);
Scalar height(Color[i][3], Color[i][4], Color[i][5]);
inRange(imgHSV, lower, height, mask);
imshow(to_string(i), mask);
}
}
VideoCapture cap(0);
//project1
int main()
{
//打开摄像头
Mat adjust1;
while (1)
{
cap >> adjust1;
findColor(adjust1);
imshow("视频", adjust1);
waitKey(10);
}
cap.release();
destroyAllWindows();
return 0;
}
读取视频
其实视频就是一张张图片,然后通过快频率从而让我们的眼睛以为他是视频
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
string path = "C:/Users/Alaso/Desktop/asd.mp4";
VideoCapture cap(path);
Mat rsv;
while (1)
{
cap.read(rsv);
imshow("image", rsv);
waitKey(20);
}
return 0;
}