ColorPicker.h说明:颜色选择器,用来过滤颜色。
ColorPicker.h:
#ifndef LESSON_1_COLORPICKER_H
#define LESSON_1_COLORPICKER_H
#include
#include
#include
#include
#include
using namespace cv;
using namespace std;
namespace ColorPicker {
const int cameraId = 0;
void color_picker() {
VideoCapture cap(cameraId);
Mat img, imgHSV, mask;
int hmin = 0, smin = 0, vmin = 0;
int hmax = 179, smax = 255, vmax = 255; // 检测的颜色范围
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);
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);
if (waitKey(1) == 1) {
break;
}
}
}
}
#endif //LESSON_1_COLORPICKER_H
如果需要自定筛选颜色(即笔的颜色),请打开宏COLOR_PICKER,调节TrackBar,使二值化效果呈现出如下图所示,便可再下面的操作中二选一:
1、将左下角的打印添加到main.cpp 第十行的myColor中(注意是vector
>类型,要用 ‘{ }’),并在main.cpp第72行myColorValues中添加笔的颜色,myColor与myColorValues一一对应,最终的效果会一次绘画多种颜色
2、将左下角的打印替换到main.cpp第十行的myColor中,并在main.cpp第72行myColorValues中更换笔的颜色
main.cpp:
#include
#include
#include
#include "ColorPicker.h"
using namespace std;
using namespace cv;
namespace DrawCanvas{
const vector<vector<int>> myColor{{107, 106, 172, 179, 222, 255}};
// 通过color_picker提取到的, hmin smin vmin hmax smax vmax
Point getContours(Mat &imgDil, Mat &img) {
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
string objType;
findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); // 检索轮廓
//drawContours(img, contours, -1, Scalar(255,0,255), 3);
vector<vector<Point>> conPloy(contours.size());
vector<Rect> boundRect(contours.size());
Point myPoint(0, 0);
for (int i = 0; i < contours.size(); ++i) {
double area = contourArea(contours[i]); // 轮廓面积
if (area >= 1000) { // 屏蔽噪音
float_t peri = arcLength(contours[i], true); // 轮廓周长
approxPolyDP(contours[i], conPloy[i], 0.02 * peri, true); // 拟合曲线
// cout << conPloy[i].size() << endl;
boundRect[i] = boundingRect(conPloy[i]); // 获取包覆轮廓的最小正矩形
myPoint.x = boundRect[i].x + boundRect[i].width / 2; // 矩形上边沿的中点
myPoint.y = boundRect[i].y;
drawContours(img, conPloy, i, Scalar(255, 0, 255), 3); // 画出近似曲线或多边形轮廓
rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);
}
}
return myPoint;
}
void findColor(Mat &img, vector<vector<int>> &newPoints) //NOLINT
{
Mat imgHSV; //NOLINT
cvtColor(img, imgHSV, COLOR_BGR2HSV);
int i = 0;
for (const auto &color : myColor) { // 选择的颜色
Scalar lower(color[0], color[1], color[2]); // hsv下限
Scalar upper(color[3], color[4], color[5]); // hsv上限
Mat mask;
inRange(imgHSV, lower, upper, mask); // 设定hsv上下限,二值化处理
imshow(to_string(i), mask);
Point point = getContours(mask, img); // 根据轮廓,获取矩形上边沿中点坐标
if (point.x != 0 && point.y != 0) {
newPoints.push_back({point.x, point.y, i}); // 第三个参数为画笔颜色索引
}
i++;
}
}
void drawOnCanvas(Mat &img, const vector<vector<int>> &newPoints, const vector<Scalar> &myColorValues) {
cout << "newPoints size: " << newPoints.size() << endl;
for (const auto &p : newPoints) {
circle(img, Point(p[0], p[1]), 10, myColorValues[p[2]], FILLED); // 画实心圆
}
}
}
// #define COLOR_PICKER // 颜色筛选
int main() {
vector<Scalar> myColorValues{{0, 0, 255}}; // 画笔颜色
vector<vector<int>> newPoints; // {{x, y, myColorValues[idx]}} 画的坐标、画笔颜色
#ifdef COLOR_PICKER
ColorPicker::color_picker();
#else
VideoCapture cap(0);
Mat img;
while(true){
cap.read(img);
DrawCanvas::findColor(img, newPoints);
DrawCanvas::drawOnCanvas(img, newPoints, myColorValues);
imshow("img", img);
if((waitKey(1) & 0xFF) == 27){
break;
}
}
#endif
return 0;
}