交通标志红孔检测法

哈工大博士王刚毅论文中提到红孔检测法,论文描述其检测效果很好,用opencv实现了一下可能是他描述的不够详细,也可能本人理解有偏差,实现方法不一致,导致我的检测效果很一般。

// Blue.cpp : 定义控制台应用程序的入口点。
//
//
#include "stdafx.h"
#include <opencv/cv.h>
#include <opencv/cxcore.h>
#include <opencv/highgui.h>
#include <cmath>
#include <iostream>
#include<vector>
#include <imgproc/imgproc.hpp>


using namespace std;
using namespace cv;
#define pi 3.1415926

int _tmain(int argc, _TCHAR* argv[])
{
	Mat img =imread("D://转移//交通标志//交通标志数据库//TEMP1//00100.jpg");
	if (!img.data)
	{
		return 0;
	}
	/*cvNamedWindow("test");
	imshow("test",img);
	cvWaitKey(0);*/


	//转到HSV
	Mat  hsv_base;
	Mat  how_red;
	cvtColor(img, hsv_base, CV_BGR2HSV );
	/*cvNamedWindow("hsv");
	imshow("hsv",hsv_base);
	cvWaitKey(0);*/
	Mat colorCut;
	colorCut.create(img.rows,img.cols,CV_32F);
	how_red.create(img.rows,img.cols,CV_32F);
	//颜色分割
	for(int x=0;x<hsv_base.rows;x++)
	{
		for(int y=0;y<hsv_base.cols;y++)
		{
			double h_src=hsv_base.at<Vec3b >(x,y)[0];
			h_src =h_src/255.0*360;
			double s_src=hsv_base.at<Vec3b >(x,y)[1];
			s_src=s_src/255;
			double v_src= hsv_base.at<Vec3b >(x,y)[2];

			if ( h_src>=300&&h_src<360)
			{
				how_red.at<float>(x,y)=s_src*sin((h_src-300.0)/180.0*pi)/sin(60.0/180*pi);
			}
			else if (h_src>=0&&h_src<=60)
			{
				how_red.at<float>(x,y)=s_src*sin((60.0-h_src)/180.0*pi)/sin(60.0/180*pi);
			}
			else
			{
			    how_red.at<float>(x,y)=0.0;
			}

				colorCut.at<float>(x,y)=0;
			if (h_src>330||(h_src<=30&&s_src>=0.2))
			{
					colorCut.at<float>(x,y)=255;
			}
		}
	}

	double *max_value ;
	double *min_value ;
	double  maxVal=0;
	double  minVal =0;
	max_value =&maxVal;
	min_value =&minVal;

	 minMaxLoc(how_red, min_value, max_value);

	/*cvNamedWindow("how");
	imshow("how",how_red);
	cvWaitKey(0);*/
	//////////////////////////////////////////////////////////////////////////
	//红色位图均值滤波//
	 //红色程度图滤波//
	Mat blueredImg ;
	Mat blueredHowRed;
	blueredImg.create(colorCut.rows,colorCut.cols,CV_32F);
	blueredHowRed.create(colorCut.rows,colorCut.cols,CV_32F);
      colorCut/=255.;
	 blur(colorCut,blueredImg,Size(7,7)); 
	 minMaxLoc(blueredImg, min_value, max_value);
	blur(how_red,blueredHowRed,Size(7,7));

	//cvNamedWindow("blur");
	//imshow("blur",blueredImg);
	//cvWaitKey(0);
	//////////////////////////////////////////////////////////////////////////
	//得到最终细化后要提取区域的图像
	Mat RefinedImg(colorCut.rows,colorCut.cols,CV_8UC1);  

	for (int x =0;x<img.rows;x++)
	{
		for (int y=0;y<img.cols;y++)
		{
			double f  =blueredHowRed.at<float>(x,y);
			double r  = blueredImg.at<float>(x,y);
		
			double ff =how_red.at<float>(x,y);
				if (r>=0.8)
				{
					RefinedImg.at<uchar>(x,y)=255;
				}
				else if (ff>=f&& r<0.8&&r>=0.2)
				{
					RefinedImg.at<uchar>(x,y)=255;
				}
				else
				{
					RefinedImg.at<uchar>(x,y)=0;
				}
		}
	}
		cvNamedWindow("last");
	    imshow("last",RefinedImg);
	    cvWaitKey(0);
		imwrite("RefinedImg.jpg",RefinedImg);
	//////////////////////////////////////////////////////////////////////////
	//开闭运算//
		dilate(RefinedImg,RefinedImg,cv::Mat());
	
		erode(RefinedImg,RefinedImg,cv::Mat());
		//dilate(RefinedImg,RefinedImg,cv::Mat());
		cvNamedWindow("bbbb");
		imshow("bbbb",RefinedImg);
		cvWaitKey(0);
	//////////////////////////////////////////////////////////////////////////
	//提取区域寻找红孔//
	 vector<vector<Point>> contours;  
	 findContours(RefinedImg,   
        contours, // a vector of contours   
        CV_RETR_EXTERNAL, // retrieve the external contours  
        CV_CHAIN_APPROX_NONE); // retrieve all pixels of each contours  
  
	 //筛选区域,太大的太小的去除//
    Mat resultt(colorCut.rows,colorCut.cols,CV_8U,Scalar(0));  
    int cmin= 100;   // minimum contour length  
    int cmax= 1000; // maximum contour length  
    vector<vector<Point>>::const_iterator itc= contours.begin();  
    while (itc!=contours.end()) {  
  
        if (itc->size() < cmin || itc->size() > cmax)  
            itc= contours.erase(itc);  
        else   
            ++itc;  
    }  
  //////////////////////////////////////////////////////////////////////////
    // draw contours on the original image//  
   //对筛选后的区域求外接多凸边形//
   vector<Point> hull;  
   vector<vector<Point>>::const_iterator itc1=contours.begin();  
    while (itc1!=contours.end())
	{        
           convexHull(Mat(*itc1),hull);  
         // Iterate over each segment and draw it  
           vector<Point>::const_iterator it= hull.begin();  
            while (it!=(hull.end()-1))
	         {  
				  line(resultt,*it,*(it+1),Scalar(255),3);  
				  ++it;  
              }  
	             line(resultt,*(hull.begin()),*(hull.end()-1),Scalar(255),3);  
                 ++itc1;               
    }  
    	 vector<vector<Point>> contours2;  
	     findContours(resultt,   
         contours2, // a vector of contours   
         CV_RETR_EXTERNAL, // retrieve the external contours  
         CV_CHAIN_APPROX_NONE);
		drawContours(resultt,contours2, -1 , Scalar(255),CV_FILLED); //填充区域。//
       	  namedWindow("ddddd");  
          imshow("ddddd",resultt); 
	      cvWaitKey(0);
		  	  minMaxLoc(resultt, min_value, max_value);
			  cout<<"max:"<<maxVal<<"min:"<<minVal<<endl;
			  
		  imwrite("resultt.jpg",resultt);
//////////////////////////////////////////////////////////////////////////
          //显示红孔
        Mat Hole(img.rows,img.cols,CV_8UC1);
		Mat res  =  imread("resultt.jpg",0);
		Mat refin= imread("RefinedImg.jpg",0);
		for (int x=0;x<img.rows;x++)
		{
			for (int y=0;y<img.cols;y++)
			{
				int rr =res.at<uchar>(x,y);
				int ff = refin.at<uchar>(x,y);
				if (rr>ff)
				{
					Hole.at<uchar>(x,y)=255;
				} 
				else
				{
					Hole.at<uchar>(x,y)=0;
				}
			}
		}
		erode(Hole,Hole,cv::Mat());
		
	    namedWindow("dddd");  
         imshow("dddd",Hole);  
	   cvWaitKey(0);
	return 0;
}

////////////////////////////////////////////////////////////////////////


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值