项目一、画笔:基于网络摄像头

1、先是用上面所用的颜色检测测出你的笔的HSV三者的值

#include<opencv2/imgcodecs.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include<iostream>

using namespace std;
using namespace cv;


int hmin = 0, smin = 0, vmin = 0;
int hmax = 179, smax = 255, vmax = 255;//如何确定这6个值,每次都更改所有这些再次运行很痛苦 -->创建跟踪栏(使我们可以实时更改这些值)
Mat img;
Mat imgHSV, mask, imgColor;

void main() {
	VideoCapture cap(0);//相机id=0
	
	
	namedWindow("Trackbars", (640, 200));//创建窗口,(640,200)是尺寸
	//运行时,把3个min的都移到最小值,把3个max的都移到最大值,然后移动使其保持为白色
	createTrackbar("Hue Min", "Trackbars", &hmin, 179);//对于hue色相饱和度最大180,对于另外两个色相饱和度最大255
	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) {
		//检查数组元素是否位于其他两个数组的元素之间。
		//imgHSV为输入图像,mask为输出图像
		cap.read(img);
		cvtColor(img, imgHSV, COLOR_BGR2HSV);//转换图像到HSV空间,在其中查找颜色更加容易
		Scalar lower(hmin, smin, vmin);
		Scalar upper(hmax, smax, vmax);
		inRange(imgHSV, lower, upper, mask);//定义颜色下限和上限,因为由于照明和不同的阴影,颜色的值将不完全相同,会是一个值的范围
		cout << hmin << "," << smin << "," << vmin << "," << hmax << "," << smax << "," << vmax << endl;
		imshow("Image", img);
		imshow("Image HSV", imgHSV);
		imshow("Image mask", mask);
		waitKey(1);//增加延时
	}
}

 2、主代码:

#include <opencv2/imgcodecs.hpp> 
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;
Mat img;
vector<vector<int>> newPoints;

///////////////  网络摄像头  //////////////////////
vector<vector<int>>myColors{//可以使用的颜色
	{0,128,0,179,255,255},//红色(hmin smin vmin hmax smax vmax)
	{0,0,3,179,255,51}//蓝色(hmin smin vmin hmax smax vmax)
};
vector<Scalar> mycolorvalues{{255,0,255},//红色
								{0,255,0}//蓝色
};

Point getContours(Mat imgDil) {//imgDil是传入的扩张边缘的图像用来查找轮廓,img是要在其上绘制轮廓的图像
	vector<vector<Point>> contours;//轮廓检测到的轮廓。每个轮廓线存储为一个点的向量

	vector<Vec4i> hierarchy;//包含关于映像拓扑的信息  typedef Vec<int, 4> Vec4i;具有4个整数值

	//在二值图像中查找轮廓。该函数利用该算法从二值图像中提取轮廓
	findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
	//drawContours(img, contours, -1, Scalar(255, 0, 255), 2);//img:要绘制轮廓在什么图片上,contours:要绘制的轮廓,-1定义要绘制的轮廓号(-1表示所有轮廓),Saclar表示轮廓颜色,2表示厚度
	
	vector<vector<Point>> conPoly(contours.size());//conploy的数量应小于contours
	vector<Rect> boundRect(contours.size());

	Point myPoint(0, 0);

	//过滤器:通过轮廓面积来过滤噪声
	for (int i = 0; i < contours.size(); i++) {//遍历检测到的轮廓
		int area = contourArea(contours[i]);
		
		//cout << area << endl;

		string objectType;
		if (area > 1000) {//轮廓面积>1000才绘制
			//计算轮廓周长或凹坑长度。该函数计算了曲线长度和封闭的周长。
			float peri = arcLength(contours[i], true);//计算封闭轮廓周长
			approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);//以指定的精度近似多边形曲线。第二个参数conPloy[i]存储近似的结果,是输出。
			cout << conPoly[i].size() << endl;
			boundRect[i] = boundingRect(conPoly[i]);//计算边界矩形

			myPoint.x = boundRect[i].x + boundRect[i].width / 2;
			myPoint.y = boundRect[i].y;

			cout << conPoly[i].size() << endl;
		    rectangle/*绘制边界矩形*/(img, boundRect[i].tl()/*tl():topleft矩形左上角坐标*/, boundRect[i].br()/*br():bottom right矩形右下角坐标*/, Scalar(0, 255, 0), 5);

			drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);
			
		}
	}
	return myPoint;
}

vector<vector<int>> findColor(Mat img) {//找点
	Mat imgHSV;
	
	cvtColor(img, imgHSV, COLOR_BGR2HSV);//转换图像到HSV空间,在其中查找颜色更加容易
	for (int i = 0; i < myColors.size(); i++)
	{
		Scalar lower(myColors[i][0], myColors[i][1], myColors[i][2]);
		Scalar upper(myColors[i][3], myColors[i][4], myColors[i][5]);
		Mat mask;
		inRange(imgHSV, lower, upper, mask);//定义颜色下限和上限,因为由于照明和不同的阴影,颜色的值将不完全相同,会是一个值的范围
		//imshow(to_string(i), mask);
		//getContours(mask);
		Point myPoint=getContours(mask);
		if (myPoint.x != 0 && myPoint.y != 0) {//没检测到东西的时候就不加入新点
			newPoints.push_back({ myPoint.x,myPoint.y,i });//i为颜色索引
		}
	}
	return newPoints;
}    
void drawOnCanvas(vector<vector<int>> newPoints, vector<Scalar> myColorValues) {//画点
	for (int i = 0; i < newPoints.size(); i++) {
		circle(img, Point(newPoints[i][0], newPoints[i][1]),6,myColorValues[newPoints[i][2]],FILLED);
	}
}
void main() {

	VideoCapture cap(0);//相机id=0
	

	while (true) {
		cap.read(img);

		newPoints = findColor(img);
		drawOnCanvas(newPoints, mycolorvalues);
		imshow("Image", img);
		waitKey(1);//增加延时 1ms,以免太慢
	}
}

效果展示: 

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐