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;
}