C++ opencv 识别火焰 (代码)

fire 


/*****************************************************************************                                                                      *                                                     *
 *  @brief    火焰识别                                                                                                                            
 *  @email    [email protected]
 *  @version  1.0.0.1(版本号)
 *  @date     2018.10.6
 *  概述:此代码用于识别图片中火焰,整体思路为通过对图像的颜色处理找出图中感兴趣区域(可能为火焰的区域)及其
 *  轮廓, 再提取轮廓的几何特征判断是否为火焰
 *  优点:在绝大多数场景下都能较为准确恰当的提取感性兴趣区域的轮廓.
 *  缺点:处理时间较慢,平均时间0.1~0.3s,个别图片1s. 对于轮廓几何特征判断做的不够完善有待提升.
 *  &&&提取感兴趣区域及其轮廓:
 *  (1)由资料得知火焰像素满足以下关系:(R > redThre &&R >= G && G>= B && S >((255 - R) * saturationTh / redThre),详细见函数findfire,由此函数实现寻找感兴趣像素点.
 *  (2)将图片转化为灰度图,直接转化为灰度图将损失大量信息.所以通过以下方式在保留有用信息同时将图片转化为灰度图:
 *      借助第一部获得的感兴趣像素点,并求出感兴趣像素点三个通道的均值 rgb[0],rgb[1],rgb[2]
 *      原图象任一点像素(B,G,R)的灰度值k表达式为 k=int(sqrt((R-rgb[0])*(R-rgb[0])+(G-rgb[1])*(G-rgb[1])+(B-rgb[2])*(B-rgb[2])))
 *      详细见函数firethreold,由此生成的灰度图既能较好地保留火焰信息,以进行进一步操作
 *  (3) 对firethreold生成的灰度图依据灰度值进行颜色聚类,使用kmeans算法,聚类数量取3(处理过的灰度图聚类速度较快,且绝大多数情况下有较好的聚类效果).详细见函数kmean_color.
 *  (4) 对聚类后的各个区域用随机颜色填充,方便后续处理,详细见函数drawcc.
 *  (5)得到的感兴趣像素点和聚类区域分布,得到最终的感兴趣区域,详细见函数sort_po.
 *  &&&提取感兴趣区域轮廓的几何特征并判断是否为火焰:
 *   通过感兴趣区域轮廓的不规则度,形态比例,边缘层次,直线角度判断是否为火焰,详细见函数judgefire.目前此部分有待完善,可后续加入尖角判定.
 *  @PS:主函数注释部分 为用meanshift进行颜色区域聚类.此算法聚类效果较好,不过基于三通道图像聚类,耗时过长,详细见函数 ShiftFiltering.
 *  @参考资料:
 *      &https://docs.opencv.org/3.4/index.html
 *      &https://blog.csdn.net/coldplayplay/article/details/70212483
 *      &https://blog.csdn.net/qq_23968185/article/details/51804574
 *
*****************************************************************************/





#include <iostream>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <math.h>
#include <time.h>
const int po_cout=4;

using  namespace std;
using namespace cv;

Mat find_fire(Mat &inImg ,int rgb[4],int redThre=49,int saturationTh=7);//寻找感兴趣像素点

Mat ShiftFiltering(Mat img1);//实现opencv meanshift聚类算法.

Mat firethreold(Mat inImg,int* rgb);//欧式距离  灰度图

Rect min_Rect(Mat data);//返回一群点的最小外接矩形

void sort_po(Mat src,Mat res, vector <Mat> &out );//根据感兴趣像素点和聚类后的区域分布提取感兴趣区域

void kmean_color(Mat pic ,Mat &src,int color_Counts);//kmean聚类算法

void drawcc(Mat &res);//对聚类后的图片填充

int judgefire(Mat fire);//判断轮廓是否为火焰

int bSums(Mat src);//求白色像素的数量

int main() {
    clock_t start,finish;
    double totaltime;
    start=clock();

    Mat data,binary;//位置分类之后的矩阵数组
    Mat original_src=imread("../f0.jpeg");
    imshow("原图",original_src);
    Mat src=original_src.clone();
    int rgb[4]={0,0,0,0};
    Mat fireimg=find_fire(src,rgb);
    imshow("感兴趣点",fireimg);
    //缩小查找范围
    Rect rect1;
    rect1=min_Rect(fireimg);
    rect1.x=rect1.x-0.1*rect1.width>0 ? rect1.x-0.1*rect1.width:rect1.x ;
    rect1.y=rect1.y-0.1*rect1.height>0 ? rect1.y-0.1*rect1.height:rect1.y ;
    rect1.width=rect1.x+rect1.width+0.2*rect1.width<src.size[1] ? rect1.width+0.2*rect1.width:rect1.width;
    rect1.height=rect1.y+rect1.height+0.2*rect1.height<src.size[0] ? rect1.height+0.2*rect1.height:rect1.height;
    binary=fireimg(rect1)/255;
    fireimg=firethreold(original_src,rgb);
    imshow("火焰色素欧式距离灰度图",fireimg);
    fireimg=fireimg(rect1);
    kmean_color(fireimg,fireimg,3);
    imshow("kmean聚类结果", fireimg);

//    dilate(fireimg, fireimg, Mat(5, 5, CV_8UC1));
//    erode(fireimg,fireimg,Mat(5, 5, CV_8UC1));

    cvtColor(fireimg,fireimg,CV_GRAY2BGR);
    drawcc(fireimg);
    imshow("彩色填充聚类结果",fireimg);

    //聚类范围与感兴趣点分布矩阵相乘
    Mat colorfire=fireimg.clone();
    for(int i=0;i<fireimg.rows;i++){
        for(int j=0;j<fireimg.cols;j++){
            if (binary.at<uchar>(i, j) == 0){
                fireimg.at<Vec3b>(i, j)=Vec3b(0, 0, 0);
            }
        }
    }
    imshow("感兴趣点与聚类区域相乘法",fireimg);

    vector <Mat> out;
    sort_po(fireimg,colorfire,out);
    RNG rng=theRNG();

//感兴趣区域轮廓判断
    Mat interesting(original_src.rows, original_src.cols, CV_8UC3, Scalar(0, 0, 0));
    for(int i=0;i<out.size();i++) {
        Scalar newVal( rng(256), rng(256), rng(256) );
        Mat original_src1=original_src.clone();
//        resize(out[i], out[i], Size(rect1.width, rect1.height));
        Mat tmp_bin(original_src1.rows, original_src1.cols, CV_8UC3, Scalar(0, 0, 0));
        Mat maskrect = tmp_bin(rect1);
        out[i].copyTo(maskrect);
        int dilation_size = 1;
        Mat element = getStructuringElement(MORPH_ELLIPSE,
                                            Size(2 * dilation_size + 1, 2 * dilation_size + 1),
                                            Point(dilation_size, dilation_size));
        dilate(tmp_bin, tmp_bin, element);

        original_src1.setTo(0, ~tmp_bin);
        cvtColor(tmp_bin,tmp_bin,CV_BGR2GRAY);
        vector<vector<Point> > contours;
        vector<Vec4i> hierarchy;
        findContours(tmp_bin, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE );
        if(judgefire(original_src1)==1){
            for( size_t i1 = 0; i1< contours.size(); i1++ ) {
                drawContours(original_src, contours, (int) i1, Scalar(0, 0, 255), 3, LINE_8, hierarchy, 0);
                drawContours(interesting, contours, (int) i1, newVal, 2, LINE_8, hierarchy, 0);
                cout<<"\n火焰!!!"<<endl;
            }

        } else{
            for( size_t i1 = 0; i1< contours.size(); i1++ ) {
                drawContours(original_src, contours, (int) i1, Scalar(0, 255, 0), 1, LINE_8, hierarchy, 0);
                drawContours(interesting, contours, (int) i1, newVal, 2, LINE_8, hierarchy, 0);

            }
        }

    }
    imshow("感兴趣区域",interesting);
    imshow("result(红色轮廓为火焰)",original_src);
    waitKey();

    finish=clock();
    totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
    cout<<"\n此程序的运行时间为"<<totaltime<<"秒!"<<endl;

    return 0;

//meanshift 颜色聚类
////    Rect rect1;
//    rect1=min_Rect(fireimg);
//    rect1.x=rect1.x-0.1*rect1.width>0 ? rect1.x-0.1*rect1.width:rect1.x ;
//    rect1.y=rect1.y-0.1*rect1.height>0 ? rect1.y-0.1*rect1.height:rect1.y ;
//    rect1.width=rect1.x+rect1.width+0.2*rect1.width<src.size[1] ? rect1.width+0.2*rect1.width:rect1.width;
//    rect1.height=rect1.y+rect1.height+0.2*rect1.height<src.size[0] ? rect1.height+0.2*rect1.height:rect1.height;
//    Mat tmp=src(rect1);
////    medianBlur ( tmp, tmp, 5 );
//    waitKey();
//    binary=fireimg(rect1)/255;
//    if(tmp.cols>200&&tmp.rows>200) {
//        resize(binary, binary, Size(200, binary.rows * 200 / binary.cols));
//        resize(tmp, tmp, Size(200, tmp.rows * 200 / tmp.cols));
//    }
//    Mat res,res1;
//    res1=ShiftFiltering(tmp);
//    res=res1.clone();
//    imshow("8",res);
//    waitKey(0);
//    for(int i=0;i<res.rows;i++){
//        for(int j=0;j<res.cols;j++){
//            if (binary.at<uchar>(i, j) == 0){
//                res.at<Vec3b>(i, j)=Vec3b(0, 0, 0);
//            }
//        }
//    }
////    clock_t start,finish;
////    double totaltime;
////    start=clock();
////    vector <Mat> out;
//    sort_po(res,res1,out);
//    for(int i=0;i<out.size();i++) {
//        resize(out[0], out[0], Size(rect1.width, rect1.height));
//        Mat tmp_bin(original_src.rows, original_src.cols, CV_8UC3, Scalar(0, 0, 0));
//        Mat maskrect = tmp_bin(rect1);
//        out[0].copyTo(maskrect);
//        int dilation_size = 1;
//        Mat element = getStructuringElement(MORPH_ELLIPSE,
//                                            Size(2 * dilation_size + 1, 2 * dilation_size + 1),
//                                            Point(dilation_size, dilation_size));
//        dilate(tmp_bin, tmp_bin, element);
//        original_src.setTo(0, ~tmp_bin);
////        imshow("233", original_src);
////        waitKey();
//
//        if(judgefire(original_src)==1){
//
//
//        };
//
//    }
//////    Mat tmp=src(rect1);
////    rect1=min_Rect(pom[i]);
////    for(int i=0;i<po_cout;i++){
////    Rect rect1;
////    rect1=min_Rect(pom[i]);
////    Mat tmp=src(rect1);
////    Point point1=Point(rect1.x,rect1.y);
////    Point point2=Point(rect1.x+rect1.width,rect1.y+rect1.height);
////
////        rectangle(src,point1,point2, Scalar(0, 255, 255), 2, 8, 0   );
////
////    }
////;
//    finish=clock();
//    totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
//    cout<<"\n此程序的运行时间为"<<totaltime<<"秒!"<<endl;
//    return 0;
}

Mat find_fire(Mat &inImg ,int* rgb,int redThre,int saturationTh){
    Mat fireImg;
    fireImg.create(inImg.size(), CV_8UC1);
    Mat multiRGB[3];
    int a = inImg.channels();
    split(inImg, multiRGB); //将图片拆分成R,G,B,三通道的颜色
    for (int i = 0; i < inImg.rows; i++)
    {
        for (int j = 0; j < inImg.cols; j++)
        {
            float B, G, R;
            B = multiRGB[0].at<uchar>(i, j); //每个像素的R,G,B值,动态地址计算法
            G = multiRGB[1].at<uchar>(i, j);
            R = multiRGB[2].at<uchar>(i, j);

            float maxValue = max(max(B, G), R);
            float minValue = min(min(B, G), R);
            //与HSI中S分量的计算公式
            double S = (1 - 3.0*minValue / (R + G + B));//

            //R > RT  R>=G>=B  S>=((255-R)*ST/RT)
            if (R > redThre &&R >= G && G>= B && S >((255 - R) * saturationTh / redThre))
            {
                fireImg.at<uchar>(i, j) = 255;
                rgb[0]+=R;
                rgb[1]+=G;
                rgb[2]+=B;
                rgb[3]+=1;
            }
            else
            {
                fireImg.at<uchar>(i, j) = 0;
            }
        }
    }

    medianBlur(fireImg, fireImg, 5);
    dilate(fireImg, fireImg, Mat(5, 5, CV_8UC1));
    for (int i=0;i<fireImg.rows;i++){
        for(int j=0;j<fireImg.cols;j++)
        {
            if(fireImg.at<uchar>(i, j) ==255){
                rgb[0]+=multiRGB[2].at<uchar>(i, j);;
                rgb[1]+=multiRGB[1].at<uchar>(i, j);
                rgb[2]+=multiRGB[0].at<uchar>(i, j);
                rgb[3]+=1;

            }
        }
    }
    rgb[0]=rgb[0]/rgb[3];
    rgb[1]=rgb[1]/rgb[3];
    rgb[2]=rgb[2]/rgb[3];
    cout<<rgb[0]<<"w"<<rgb[1]<<"w"<<rgb[2]<<"w";
    return fireImg;

    //erode(fireImg, fireImg, Mat(3, 3, CV_8UC1));
    //GaussianBlur(fireImg, fireImg, Size(5, 5), 0, 0);


//    kmean_Point(fireImg,inImg);
//    DrawFire(inImg, fireImg);
//    return fireImg;
}

Rect min_Rect(Mat M){
    Mat data;
    if (M.channels()!=1){
        cvtColor(M,M,CV_BGR2GRAY);}
    for(int i=0;i<M.rows;i++){
        for(int j=0;j<M.cols;j++){
            if ((int)M.at<uchar>(i, j)!=0){
                Mat tmp = (Mat_<float>(1, 2)<< i, j);
                data.push_back(tmp);
            }
        }
    }
    double minvx,maxvx;
    double* minpx = &minvx;
    double* maxpx = &maxvx;
    double minvy,maxvy;
    double* minpy = &minvy;
    double* maxpy = &maxvy;
    minMaxIdx(data.col(1),minpx,maxpx);
    minMaxIdx(data.col(0),minpy,maxpy);
    Rect g_rectangle;
    g_rectangle=Rect(minvx,minvy,maxvx-minvx,maxvy-minvy);
    return g_rectangle;
}

Mat ShiftFiltering(Mat img1){

    clock_t start,finish;
    double totaltime;
    start=clock();
    Mat img(img1);
//    resize(img1,img,Size(150,150));
    Mat res; //分割后图像
    int spatialRad,colorRad;
    if(img1.rows*img1.cols>40000)
    {
        cout<<112;
        spatialRad = 50;  //空间窗口大小
        colorRad = 50;   //色彩窗口大小}
    }else{

        spatialRad = 40;  //空间窗口大小
        colorRad = 30; }
    int maxPyrLevel = 2;  //金字塔层数
    pyrMeanShiftFiltering( img, res, spatialRad, colorRad, maxPyrLevel); //色彩聚类平滑滤波
    RNG rng = theRNG();
    Mat mask( res.rows+2, res.cols+2, CV_8UC1, Scalar::all(0) );  //掩模
    int n=0;
    for( int y = 0; y < res.rows; y++ )
    {
        for( int x = 0; x < res.cols; x++ )
        {
            if( mask.at<uchar>(y+1, x+1) == 0 )  //非0处即为1,表示已经经过填充,不再处理
            {

                Scalar newVal( rng(256), rng(256), rng(256) );
                floodFill( res, mask, Point(x,y), newVal, 0, Scalar::all(5), Scalar::all(5) ); //执行漫水填充
            }
        }
    }
    finish=clock();
    totaltime=(double)(finish-start)/CLOCKS_PER_SEC;

    cout<<"\n此程序的运行时间为"<<totaltime<<"秒!"<<endl;
//    imshow("meanShift图像分割", res );
////    imshow("res",res);
//    waitKey();
    return res;
}

void sort_po(Mat src,Mat res, vector <Mat> &outlist ){
    vector <Vec3f> Po_value;
    vector <Mat> Po;
    int count=0;
    for(int i=0;i<src.rows;i++){
      for(int j=0;j<src.cols;j++){
          Vec3f point =src.at<Vec3b>(i, j);
          Vec3f point1=(0,0,0);
          if (point!=point1) {
              count++;
              int ju1 = 0;

              for (int it = 0; it < Po_value.size(); it++) {
                  if (point == Po_value[it]) {
                      Mat tmp = (Mat_<float>(1, 2) << i, j);
                      Po[it].push_back(tmp);
//                      cout << 1;
                      ju1=1;
                  }

                  }

              if (ju1 == 0) {
                  Po_value.push_back(point);
                  Mat tmp2 = (Mat_<float>(1, 2) << i, j);
                  Po.push_back(tmp2);
              }
          } else{}
      }
    }
    for (int i1=0 ;i1<Po.size();i1++){
        if (Po[i1].rows<count/10){
            continue;
        } else{
            vector<Point > contours;
            vector<Point>hull;

            for(int i=0;i<Po[i1].rows;i++){
                    Point tmp=Point(Po[i1].at<float>(i,1),Po[i1].at<float>(i,0));
                    contours.push_back(tmp);
            }
            convexHull( contours, hull );

            vector<vector<Point> > h={hull};
//            Mat tp(res.rows,res.cols,CV_8UC3);
//            drawContours( res, h, (int)0, Scalar(255,255,255) ,2);
//            imshow("3",res);
//            waitKey();
            double s=0;
            double g_dConArea = contourArea(hull, true);
            Mat out=res.clone();
            for (int i=0;i<res.rows;i++){
                for(int j=0;j<res.cols;j++){
                    Vec3f value=out.at<Vec3b>(i,j);
                    if(value==Po_value[i1]){
                        s++;
                        out.at<Vec3b>(i,j)=Vec3b(255,255,255);
                    } else{out.at<Vec3b>(i,j)=Vec3f(0,0,0);}
                }

            }
            if (g_dConArea>0.7*s&&s>0.5*g_dConArea){
                outlist.push_back(out);
            }


        }

    }

}


int bSums(Mat src) {

    int counter = 0;
    //迭代器访问像素点
    Mat_<uchar>::iterator it = src.begin<uchar>();
    Mat_<uchar>::iterator itend = src.end<uchar>();
    for (; it!=itend; ++it)
    {
        if((*it)>0) counter+=1;//二值化后,像素点是0或者255
    }
    return counter;
}

Mat firethreold(Mat inImg,int rgb[4]){
    Mat fireImg;
    fireImg.create(inImg.size(), CV_8UC1);
    Mat multiRGB[3];
    int a = inImg.channels();
    split(inImg, multiRGB); //将图片拆分成R,G,B,三通道的颜色
    for (int i = 0; i < inImg.rows; i++)
    {
        for (int j = 0; j < inImg.cols; j++)
        {
            float B, G, R;
            B = multiRGB[0].at<uchar>(i, j); //每个像素的R,G,B值,动态地址计算法
            G = multiRGB[1].at<uchar>(i, j);
            R = multiRGB[2].at<uchar>(i, j);

            int k=int(sqrt((R-rgb[0])*(R-rgb[0])+(G-rgb[1])*(G-rgb[1])+(B-rgb[2])*(B-rgb[2])));
            if (k>255){
                k=255;
            }
            k=255-k;

                fireImg.at<uchar>(i, j) = k;
            }
        }
    return fireImg;



}

void kmean_color(Mat pic ,Mat &src,int color_Counts){
    const int MAX_CLUSTERS = 5;
    float colorTab[] =
            {
//                    Vec3b(0, 0, 255),
//                    Vec3b(0, 255, 0),
//                    Vec3b(255, 100, 100),
//                    Vec3b(255, 0, 255),
//                    Vec3b(0, 255, 255)
                    0,
                    100,
                    255,
                    150
            };
    Mat data,labels;
//    Mat pic = imread("d:/woman.png");
    for (int i = 0; i < pic.rows;i++)
        for (int j = 0; j < pic.cols; j++)
        {
            uchar point = pic.at<uchar >(i, j);
            Mat tmp = (Mat_<float >(1, 1) << point);
            data.push_back(tmp);
        }
        //根据浏览图片,确定k=3
    kmeans(data, 3, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0),
           3, KMEANS_RANDOM_CENTERS);

    int n = 0;
    //显示聚类结果,不同的类别用不同的颜色显示
    for (int i = 0; i < pic.rows; i++)
        for (int j = 0; j < pic.cols; j++)
        {
            int clusterIdx = labels.at<int>(n);
            pic.at<uchar >(i, j) =(uchar)colorTab[clusterIdx];
            n++;
        }

}

void drawcc(Mat &res){

    RNG rng = theRNG();
    Mat mask( res.rows+2, res.cols+2, CV_8UC1, Scalar::all(0) );  //掩模
    int n=0;
    for( int y = 0; y < res.rows; y++ )
    {
        for( int x = 0; x < res.cols; x++ )
        {
            if( mask.at<uchar>(y+1, x+1) == 0 )  //非0处即为1,表示已经经过填充,不再处理
            {

                Scalar newVal( rng(256), rng(256), rng(256) );
                floodFill( res, mask, Point(x,y), newVal, 0, Scalar::all(5), Scalar::all(5) ); //执行漫水填充
            }
        }
    }
}

int judgefire(Mat fire){
    Mat gray,bin ,candy;
    int judge;
    cvtColor(fire,gray,CV_BGR2GRAY);
    threshold(gray, bin,1, 255, THRESH_BINARY );
    Canny( bin, candy, 40, 40*3, 3 );
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    findContours( bin, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE );
    Mat drawing = Mat::zeros( bin.size(), CV_8UC3 );
    double k;


//    int maxCorners = 5;
//    Mat c(bin.rows,bin.cols,CV_8UC1);
//    findcorner(c,contours,hierarchy);
//    RNG rng(12345);
//    vector<Point2f> corners;
//    double qualityLevel = 3;
//    double minDistance = 50;
//    int blockSize = 20, gradientSize = 3;
//    bool useHarrisDetector = false;
//    double k1 = 0.04;
//    Mat copy =bin.clone();
//    goodFeaturesToTrack( bin,
//                         corners,
//                         maxCorners,
//                         qualityLevel,
//                         minDistance,
//                         Mat(),
//                         blockSize,
//                         gradientSize,
//                         useHarrisDetector,
//                         k1 );
//    cout << "** Number of corners detected: " << corners.size() << endl;
//    int radius = 4;
//    for( size_t i = 0; i < corners.size(); i++ )
//    {
//        cout<<corners[i]<<"\n";
//        circle( fire, corners[i], radius, Scalar(rng.uniform(0,255), rng.uniform(0, 256), rng.uniform(0, 256)), FILLED );
//    }

    int coutc=0;
    for( size_t i = 0; i< contours.size(); i++ ) {
        drawContours(drawing, contours, (int) i, Scalar(255, 0, 0), 2, LINE_8, hierarchy, 0);
        if (abs(contourArea(contours[i], true)) > 300) {
            if (coutc==1){
                judge=0 ;
                break;
            }
            coutc++;

            k = arcLength(contours[i], false) * arcLength(contours[i], false) / contourArea(contours[i], true);//k 为不规则度,k越大越不规则;
            vector<Vec4i> linesP; // will hold the results of the detection

            HoughLinesP(candy, linesP, 1, CV_PI / 180, 50, 50, 10); // runs the actual detection
            // Draw the lines
            for (size_t i = 0; i < linesP.size(); i++) {
                Vec4i l = linesP[i];
                line(drawing, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, LINE_AA);
            }
//            imshow("asd", drawing);
//            waitKey();
            if (abs(k) <= 40) {
                judge = 0;

                for (size_t i1 = 0; i1 < linesP.size(); i1++) {
                    Vec4i l = linesP[i1];
//                    line( drawing, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
                    if (abs((l[1] - l[3]) / (l[0] - l[2]+0.1) < 1) ){
                        judge = 0;
                        break;
                    }
//                     double  sita=atan();
                }
                Rect rect = min_Rect(bin);
                cout<<rect.height <<"dwdqa"<< rect.width;
                if (rect.height > rect.width * 1.2) {
                    judge = 1;
                } else {
                    judge = 0;
                    break;
                }
                Rect recth = Rect(rect.x, rect.y, (int) (rect.height / 2), rect.width);
                Rect rectl = Rect(rect.x, rect.y + (int) (rect.height / 2), (int) (rect.height / 2), rect.width);
                int sl = bSums(bin(rectl));
                int sh = bSums(bin(recth));
                if (sl > 1.2 * sh) {
                    judge = 1;
                } else { judge = 0; }
            } else {
                judge=1;
                vector<Point> hull1;
                convexHull( contours[i], hull1 );
                int sh=contourArea(hull1, true);
                int sa=bSums(bin);
                if(sa<0.5*sh){
                    judge=0;
                    break;
                }

                for (size_t i1 = 0; i1 < linesP.size(); i1++) {
                    Vec4i l = linesP[i1];
//                    line( drawing, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
                    if (abs((l[1] - l[3]) / (l[0] - l[2]+0.1)) < 1 || (l[1] - l[3]) / (l[0] - l[2]+0.1) > 20) {
                        if(sqrt((l[1] - l[3])*(l[1] - l[3])+(l[0] - l[2])*(l[0] - l[2]))>arcLength(contours[i], false)*0.1) {
                            judge = 0;
                            break;
                        }

                    }

                }

            }
        }
    }

//    HoughLinesP(candy, linesP, 1, CV_PI/90, 30, 40, 10); // runs the actual detection
//    // Draw the lines
//    for( size_t i = 0; i < linesP.size(); i++ )
//    {
//        Vec4i l = linesP[i];
//        line(fire, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
//    }
//    imshow("sads",fire);
//    cout<<"adwdaw"<<judge<<"\n";
    return judge;

}

猜你喜欢

转载自blog.csdn.net/weixin_41962365/article/details/82959043