如果需要自定筛选颜色(即笔的颜色),请打开宏COLOR_PICKER,筛选结束后再注释
ColorPicker.h:
//
// Created by Administrator on 2022/4/16.
// 颜色筛选
//
#ifndef LESSON_1_COLORPICKER_H
#define LESSON_1_COLORPICKER_H
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect.hpp>
#include <iostream>
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 min", "TrackBars", &smax, 255);
createTrackbar("Val min", "TrackBars", &vmin, 255);
createTrackbar("Val min", "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
颜色选择效果:
main.cpp:
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "ColorPicker.h"
using namespace std;
using namespace cv;
namespace DrawCanvas{
const vector<vector<int>> myColor{{107, 106, 172, 179, 222, 255}}; // 通过color_picker提取到的hsv, 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]), 5, 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;
}