使用opencv(c++)实现虚拟画布

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中更换笔的颜色

颜色选择效果:
使用opencv(c++)实现虚拟画布_第1张图片

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;
}

最终的效果图:
使用opencv(c++)实现虚拟画布_第2张图片

你可能感兴趣的:(opencv,c++,opencv,图像处理)