OpenCV虚拟画图程序(C++)

参考4h上手C++版Opencv_Bilibili

OpenCV版本:4.5.5

ColorPicker.cpp

//OpenCV版本:4.5.5
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;

Mat imgHSV, mask, imgColor;
int hmin = 24, smin = 95, vmin = 105;
int hmax = 80, smax = 245, vmax = 255;
//24,95,105,80,245,255
VideoCapture cap(0);
Mat img;
int main()
{
	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)
	{
		//cap.read(img);
		cap >> img;

		cvtColor(img, imgHSV, COLOR_BGR2HSV);

		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("Mask", mask);

		waitKey(1);
	}
}

VisualPaint.cpp

//OpenCV版本:4.5.5
#include <opencv2\opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
using namespace std;

//尽量在光照稳定的环境中运行此程序,背景最好是纯色并且与画笔的颜色差异较大
Mat img;
vector<vector<int>> newPoints;
//要检测的颜色(HSV模式)(顺序为hmin smin vmin hmax smax vmax)(通过ColorPicker.cpp手动调出范围)
//vector<vector<int>> myColors{ {21,105,125,55,230,230} };//黄色塑料壳固体胶的颜色
//140,65,110,195,150,195比较宽松的红色
vector<vector<int>> myColors{ {130,55,85,205,160,210} }; //更加宽松的红色
//要输出的颜色
vector<Scalar> myColorValues{ {0,0,255} };

Point getContours(Mat imgDil)
{
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;

	findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

	vector<vector<Point>> conPoly(contours.size());
	vector<Rect> boundRect(contours.size());

	Point myPoint(0, 0);//笔尖坐标
	int max = -1;//储存面积最大的区域的下标

	for (int i = 0; i < contours.size(); i++)
	{
		if (contourArea(contours[i]) > 0)
		{
			绘制边缘
			//float peri = arcLength(contours[i], true);
			//approxPolyDP(contours[i], conPoly[i], 0.01 * peri, true);
			//drawContours(img, conPoly, i, Scalar(255, 0, 255), 3);
			cout << conPoly[i].size() << endl;
			绘制矩形框
			//boundRect[i] = boundingRect(conPoly[i]);
			//rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0));
			//找出面积最大的区域
			if (max != -1) 
			{
				if (contourArea(contours[i]) > contourArea(contours[max]))max = i;
			}
			else max = i;
		}
	}
	
	if (max != -1)
	{
		//绘制边缘
		float peri = arcLength(contours[max], true);
		approxPolyDP(contours[max], conPoly[max], 0.01 * peri, true);
		drawContours(img, conPoly, max, Scalar(255, 0, 255), 3);
		//cout << conPoly[i].size() << endl;
		//绘制矩形框
		boundRect[max] = boundingRect(conPoly[max]);
		rectangle(img, boundRect[max].tl(), boundRect[max].br(), Scalar(0, 255, 0));
		//获取面积最大的区域(视为笔尖)的坐标
		myPoint.x = boundRect[max].x + boundRect[max].width / 2;
		myPoint.y = boundRect[max].y;
	}
	return myPoint;
}

vector<vector<int>> findColor(Mat img)
{
	Mat imgHSV;
	cvtColor(img, imgHSV, COLOR_BGR2HLS);
	int max = 0;
	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);
		Point myPoint=getContours(mask);
		if (myPoint.x != 0 && myPoint.y != 0)
		{
			newPoints.push_back({ myPoint.x,myPoint.y,i });//将符合条件的笔尖坐标和相应颜色存入newPoints
		}
	}
	return newPoints;
}

Point prepoint;//储存前一个点的坐标
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]), 5, myColorValues[newPoints[i][2]], FILLED);

		//用线段连接将前后相邻(指时间顺序的前后)且距离比较进的点连起来
		//由于本程序只识别一个颜色所以可以正常运行,若要识别多个颜色需要使用一组点,如vector<Point> prepoint;
		if (i >0&&sqrt((newPoints[i][0]-prepoint.x)* (newPoints[i][0] - prepoint.x)+ (newPoints[i][1] - prepoint.y) * (newPoints[i][1] - prepoint.y))<50)
			line(img, prepoint, Point(newPoints[i][0], newPoints[i][1]), myColorValues[newPoints[i][2]], 10);
		prepoint = Point(newPoints[i][0], newPoints[i][1]);
	}
}

int main()
{
	//读取视频或摄像头
	VideoCapture capture(0);

	while (true)
	{
		capture.read(img);
		//capture >> img;
		//newPoints = findColor(img);
		findColor(img);
		drawOnCanvas(newPoints,myColorValues);
		imshow("读取视频", img);
		waitKey(1);
	}
	return 0;
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值