实时寻找红色的物体

第六届光电设计竞赛

这里写图片描述

/*****************************************************************************************
光电设计竞赛程序
2018.7.3:找红灯






*****************************************************************************************/
#include<opencv2/opencv.hpp>
#include<iostream>
#define PI 3.1415926

using namespace std;
using namespace cv;



//RGB转HSV
void RGB2HSV(double red, double green, double blue, double& hue, double& saturation, double& intensity)
{

    double r, g, b;
    double h, s, i;

    double sum;
    double minRGB, maxRGB;
    double theta;

    r = red / 255.0;
    g = green / 255.0;
    b = blue / 255.0;

    minRGB = ((r<g) ? (r) : (g));
    minRGB = (minRGB<b) ? (minRGB) : (b);

    maxRGB = ((r>g) ? (r) : (g));
    maxRGB = (maxRGB>b) ? (maxRGB) : (b);

    sum = r + g + b;
    i = sum / 3.0;

    if (i<0.001 || maxRGB - minRGB<0.001)
    {
        h = 0.0;
        s = 0.0;
    }
    else
    {
        s = 1.0 - 3.0*minRGB / sum;
        theta = sqrt((r - g)*(r - g) + (r - b)*(g - b));
        theta = acos((r - g + r - b)*0.5 / theta);
        if (b <= g)
            h = theta;
        else
            h = 2 * PI - theta;
        if (s <= 0.01)
            h = 0;
    }

    hue = (int)(h * 180 / PI);
    saturation = (int)(s * 100);
    intensity = (int)(i * 100);
}


//填充
void fillHole(const Mat srcBw, Mat &dstBw)
{
    Size m_Size = srcBw.size();
    Mat Temp = Mat::zeros(m_Size.height + 2, m_Size.width + 2, srcBw.type());//延展图像
    srcBw.copyTo(Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)));

    cv::floodFill(Temp, Point(0, 0), Scalar(255));//填充区域

    Mat cutImg;//裁剪延展的图像
    Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)).copyTo(cutImg);

    dstBw = srcBw | (~cutImg);
}

int main()
{


    int iiii = 1000;

    Mat frame;
    Mat srcImg;




    //【1】从摄像头读入视频
    VideoCapture capture(1);  //该参数为0,则打开计算机自带摄像头,如果为1则打开外置USB摄像头


    //capture.set(CAP_PROP_FRAME_WIDTH, 1920.0);//设置摄像头采集图像分辨率
    //  capture.set(CAP_PROP_FRAME_HEIGHT, 1080.0);
    while (1)
    {


        //iiii++;
        隔一段时间保存一张图片
        //if (iiii >= 50)//通过改变i后面的值来刷新图片界面
        //{
        //iiii = 0;
        clock_t start = clock();
        capture >> frame;// //读取当前帧,capture >> frame与capture.read(frame)功能一样,
        if (frame.empty())
        {
            return 0;
        }
        //srcImg = imread("2.jpg");//读取文件
        resize(frame, srcImg, Size(200, 200));//重定义图片大小
        namedWindow("原图", 0);
        imshow("原图", srcImg);
        waitKey(1);
        int width = srcImg.cols;
        int height = srcImg.rows;

        int x, y;
        double B = 0.0, G = 0.0, R = 0.0, H = 0.0, S = 0.0, V = 0.0;
        Mat vec_rgb = Mat::zeros(srcImg.size(), CV_8UC1);
        for (x = 0; x < height; x++)
        {
            for (y = 0; y < width; y++)
            {
                B = srcImg.at<Vec3b>(x, y)[0];
                G = srcImg.at<Vec3b>(x, y)[1];
                R = srcImg.at<Vec3b>(x, y)[2];
                RGB2HSV(R, G, B, H, S, V);
                //红色范围,范围参考的网上。可以自己调
                if ((H >= 312 && H <= 360 || H >= 0 && H <= 20) && (S >= 17 && S <= 100) && (V>18 && V < 100))
                    vec_rgb.at<uchar>(x, y) = 255;
            }
        }

        namedWindow("hsv", 0);
        imshow("hsv", vec_rgb);
        waitKey(1);
        medianBlur(vec_rgb, vec_rgb, 3);//中值滤波
        namedWindow("中值滤波", 0);
        imshow("中值滤波", vec_rgb);
        waitKey(1);
        Mat element = getStructuringElement(MORPH_ELLIPSE, Size(2 * 1 + 1, 2 * 1 + 1), Point(1, 1));
        Mat element1 = getStructuringElement(MORPH_ELLIPSE, Size(2 * 3 + 1, 2 * 3 + 1), Point(3, 3));
        erode(vec_rgb, vec_rgb, element);//腐蚀

        namedWindow("腐蚀", 0);
        imshow("腐蚀", vec_rgb);
        waitKey(1);
        dilate(vec_rgb, vec_rgb, element1);//膨胀

        namedWindow("膨胀", 0);
        imshow("膨胀", vec_rgb);
        waitKey(1);
        fillHole(vec_rgb, vec_rgb);//填充

        namedWindow("填充", 0);
        imshow("填充", vec_rgb);
        waitKey(1);

        vector<vector<Point>>contours; //轮廓
        vector<Vec4i> hierarchy;//分层

        Point  zhongdian; //红色灯的中点

        findContours(vec_rgb, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));//寻找轮廓

        vector<vector<Point>> contours_poly(contours.size());  //近似后的轮廓点集
        vector<Rect> boundRect(contours.size());  //包围点集的最小矩形vector
        vector<Point2f> center(contours.size());  //包围点集的最小圆形vector
        vector<float> radius(contours.size());  //包围点集的最小圆形半径vector

        for (int i = 0; i < contours.size(); i++)
        {
            approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true); //对多边形曲线做适当近似,contours_poly[i]是输出的近似点集
            boundRect[i] = boundingRect(Mat(contours_poly[i])); //计算并返回包围轮廓点集的最小矩形
            minEnclosingCircle(contours_poly[i], center[i], radius[i]);//计算并返回包围轮廓点集的最小圆形及其半径
        }

        Mat drawing = Mat::zeros(vec_rgb.size(), CV_8UC3);
        for (int i = 0; i < contours.size(); i++)
        {
            Scalar color = (0, 0, 255);//蓝色线画轮廓
            drawContours(drawing, contours_poly, i, color, 1, 8, hierarchy, 0, Point());//根据轮廓点集contours_poly和轮廓结构hierarchy画出轮廓
            rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);//画矩形,tl矩形左上角,br右上角
            circle(drawing, center[i], (int)radius[i], color, 2, 8, 0);                                        //画圆形
        }

        /// 显示在一个窗口
        namedWindow("包围最小矩形和圆形", 0);
        imshow("包围最小矩形和圆形", drawing);
        waitKey(1);

        clock_t ends = clock();
        cout << "Running Time : " << (double)(ends - start) / CLOCKS_PER_SEC << endl;
    }
    waitKey();
    return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

翟羽嚄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值