opencv 颜色识别hsv方法 C++(红色)

时间:2023-03-21
本文章向大家介绍opencv 颜色识别hsv方法 C++(红色),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

本文采用的是hsv的方式进行颜色识别,主要流程如下: 

  1. 读取视频 :VideoCapture cap(0);
  2. 设置图像参数:cap.set(cv::CAP_PROP_FRAME_WIDTH, width);设置图像宽度。
  3. 将图像转换为HSV颜色空间:cvtColor(frame, hsv, COLOR_BGR2HSV)
  4. 调整hsv的范围
  5. 对图像进行二值化处理 inRange(hsv, lower_yellow, upper_yellow, mask);
  6. 对二值化后的图像进行形态学处理,去除噪点:

    Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
    morphologyEx(mask2, mask2, MORPH_OPEN, kernel);
    morphologyEx(mask2, mask2, MORPH_CLOSE, kernel);

  7. 高斯滤波:GaussianBlur(mask2, mask2, Size(3, 3), 0);
  8. canny算子边缘检测:Canny(mask2, mask2, 100, 250);
  9. 在二值化后的图像中寻找轮廓
  10. 计算轮廓的面积
  11. 寻找面积最大的部分
  12. 绘制轮廓的最小外接正矩形
    #include <opencv2/imgcodecs.hpp>
    #include <opencv2/highgui.hpp>
    #include <opencv2/imgproc.hpp>
    #include <iostream>
    #include <vector>
    using namespace cv;
    using namespace std;
    
    int width = 800; // 设置图像宽度
    int height = 600; // 设置图像高度
    //readme 可以识别红色hsv 
    
    
    int main() {
    
    
        VideoCapture cap(0);//读取视频0
    
    
        cap.set(cv::CAP_PROP_FRAME_WIDTH, width); // 设置图像宽度
        cap.set(cv::CAP_PROP_FRAME_HEIGHT, height); // 设置图像高度
    
    
    
    
        while (true)
        {
            int max = 0;
            Mat frame;
            cap.read(frame);
            Mat hsv;
            cvtColor(frame, hsv, COLOR_BGR2HSV);// 将图像转换为HSV颜色空间
    
            cv::Scalar lower_yellow(7, 94, 82);
            cv::Scalar upper_yellow(54, 232, 255); // 定义黄色的HSV范围
    
            cv::Scalar lower_red(137, 144, 114);
            cv::Scalar upper_red(255, 241, 242); // 定义红色的HSV范围
    
    
            Mat mask;
            Mat mask2;
            inRange(hsv, lower_yellow, upper_yellow, mask);// 对图像进行二值化,只保留蓝色部分
            inRange(hsv, lower_red, upper_red, mask2);
            // 对二值化后的图像进行形态学处理,去除噪点
            Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
            morphologyEx(mask2, mask2, MORPH_OPEN, kernel);
            morphologyEx(mask2, mask2, MORPH_CLOSE, kernel);
            GaussianBlur(mask2, mask2, Size(3, 3), 0);//高斯滤波
            Canny(mask2, mask2, 100, 250);//canny算子边缘检测
    
    
            // 在二值化后的图像中寻找轮廓
            vector<vector<Point>> contours;
            vector<Vec4i> hierarchy;
            findContours(mask2, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
    
            Mat mask2Contours = Mat::zeros(mask2.size(), CV_8UC1);
            Mat Contours = Mat::zeros(mask2.size(), CV_8UC1);
            Mat mask2Contours0 = Mat::zeros(mask2.size(), CV_8UC1);
            vector<double> g_dConArea(contours.size());
            for (int i = 0; i < contours.size(); i++)
            {
                //contours[i]代表的是第i个轮廓,contours[i].size()代表的是第i个轮廓上所有的像素点数  
                for (int j = 0; j < contours[i].size(); j++)
                {    //绘制出contours向量内所有的像素点  
                    //Point P = Point(contours[i][j].x, contours[i][j].y);
                    //Contours.at<uchar>(P) = 255;
                    //计算轮廓的面积
                    g_dConArea[i] = contourArea(contours[i]);
                }
                //寻找面积最大的部分
                
                for (int i = 1; i < contours.size(); i++) {
                    if (g_dConArea[i] > g_dConArea[max]) {
                        max = i;
                    }
                    
                }
    
    
            }
            //Point pt1(200, 100);
            //Point pt2(600, 500);
            drawContours(mask2Contours, contours, max, Scalar(255), 1, 8, hierarchy);
            //绘制轮廓的最小外接正矩形
            Rect boundRect = boundingRect(Mat(contours[max]));
            rectangle(mask2Contours0, Point(boundRect.x, boundRect.y), Point(boundRect.x + boundRect.width, boundRect.y + boundRect.height), Scalar(255), 2, 8);
            //中心点Point(boundRect.x+boundRect.width/2,boundRect.y+boundRect.height/2);
            //绘制轮廓的最小外结矩形
            circle(frame, Point(boundRect.x + boundRect.width/2, boundRect.y + boundRect.height/2), 5, Scalar(255), -1);
    
    
            
    
            RotatedRect rect = minAreaRect(contours[max]);
            Point2f P[4];//初始化矩形四个顶点坐标
            rect.points(P);
            for (int j = 0; j <= 3; j++)
            {
                line(mask2Contours, P[j], P[(j + 1) % 4], Scalar(255), 2);
                line(frame, P[j], P[(j + 1) % 4], Scalar(255), 2);
    
            }
        
            
            if (waitKey(1) == 'q')
                break;
    
    
    
            imshow("hsv", hsv);
            imshow("mask", mask);
            imshow("mask2", mask2);
            /*imshow("contours", contours);*/
            imshow("Color Detection", frame);
            imshow("最小正外接矩形", mask2Contours0);
            imshow("Contours Image", mask2Contours); //轮廓
            //imshow("Point of Contours", Contours);   //向量contours内保存的所有轮廓点集 
        }
    
        // 释放摄像头资源和所有窗口
        cap.release();
        destroyAllWindows();
    
        return 0;
    
    
    
    
    }

    写的垃圾,大佬多多指教。

  13. 效果图1:
  14.  颜色随便提取的(大家也可以尝试用提取通道的方法)

原文地址:https://www.cnblogs.com/shlmqq/p/17238567.html