Opencvナンバープレート抽出を実現

3515 ワード

エッジ検出−形態学−矩形領域抽出を用いて最終的なナンバープレートを得た
コードと詳細な説明は次のとおりです.
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
//     sobel  
void SobelVerEdge(Mat& src, Mat& result)
{
	CV_Assert(src.channels()==1);
	src.convertTo(src,CV_32FC1);
	//     sobel  ,            180 
	Mat sobelx = (Mat_(3,3)<pDataMag[i*nCols + j-1]);
			bool b2 = (pDataMag[i*nCols + j]>pDataMag[i*nCols + j + 1]);
			bool b3 = (pDataMag[i*nCols + j]>pDataMag[(i-1)*nCols + j]);
			bool b4 = (pDataMag[i*nCols + j]>pDataMag[(i + 1)*nCols + j]);
			pDataRes[i*nCols + j] = 255 * ((pDataMag[i*nCols + j] > thresh) && ((b1&&b2) || (b3&&b4)));
		}
	}
	resultTemp.convertTo(resultTemp,CV_8UC1);
	result = resultTemp.clone();
}

//      
Mat getPlateArea(Mat& src, Mat SobelMat)
{
	//    ,       ,        HSV  ,          
	Mat img_h, img_s, img_v, imghsv;
	vector hsv_vec;
	cvtColor(src,imghsv,CV_BGR2HSV);
	imshow("hsv",imghsv);
	waitKey(0);
	//  hsv  
	split(imghsv,hsv_vec);
	img_h = hsv_vec[0];
	img_s = hsv_vec[1];
	img_v = hsv_vec[2];
	img_h.convertTo(img_h,CV_32F);
	img_s.convertTo(img_s, CV_32F);
	img_v.convertTo(img_v, CV_32F);
	double max_s, max_h, max_v;
//    ,      Mat  ,   :double* minValue,   :double* maxValue, int minIdx,int maxIdx
	minMaxIdx(img_h,0,&max_h);
	minMaxIdx(img_s, 0, &max_s);
	minMaxIdx(img_v, 0, &max_v);
	//      
	img_h = img_h / max_h;
	img_s = img_s / max_s;
	img_v = img_v / max_v;
	//       
	Mat bw_blue = ((img_h > 0.45) & (img_h<0.75) &(img_s>0.15) &(img_v > 0.25));
	int height = bw_blue.rows;
	int width = bw_blue.cols;
	Mat bw_blue_edge = Mat::zeros(bw_blue.size(),bw_blue.type());
	imshow("bw_blue",bw_blue);
	waitKey(0);
	//        ,      ,         
	for (int k = 1; k < height - 1; k++)
	{
		for (int l = 1; l < width - 1; l++)
		{
			Rect rct;
			rct.x = l - 1;
			rct.y = k - 1;
			rct.height = 3;
			rct.width = 3;
			if ((SobelMat.at(k, l) == 255) && (countNonZero(bw_blue(rct)>1)))
				bw_blue_edge.at(k, l) = 255;
		}
	}
	//     
	Mat morph;
	morphologyEx(bw_blue_edge,morph,MORPH_CLOSE,Mat::ones(2,25,CV_8UC1));
	imshow("morph",morph);
	vector> region_contours;
	findContours(morph.clone(),region_contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,Point(0,0));
	Mat result;
	for (int n = 0; n < region_contours.size(); n++)
	{
		//          0         ,     
		Rect rect = boundingRect(region_contours[n]);//            
		int sub = countNonZero(morph(rect));//          0    
		double ratio = double(sub) / rect.area();//                         
		double wh_ratio = double(rect.width) / rect.height;
		if (ratio > 0.5 && wh_ratio > 2 && wh_ratio < 5 && rect.height>12 && rect.width > 60)
		{
			result = src(rect);
			imshow("Rect",result);
			waitKey(0);
		}

	}
	return result;
}

int main()
{
	//imread 0      ,1      
	Mat srcImage = imread("E:\\   \\    \\    \\OpenCV        -  -20160801\\《OpenCV        -  -20160801\\images\\car.jpg");
	if (!srcImage.data)
		return -1;
	Mat srcGray;
	cvtColor(srcImage,srcGray,CV_BGR2GRAY);
	Mat sobelMat;
	SobelVerEdge(srcGray, sobelMat);
	Mat result = getPlateArea(srcImage,sobelMat);
	return 0;
}