add getPlateColor and changeParam method

1.3
Fenix 11 years ago
parent c4cea7de77
commit 93f302b303

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 200 KiB

@ -29,7 +29,7 @@ const int numAll = 54; /* 34+20=54 */
CCharsIdentify::CCharsIdentify()
{
cout << "CCharsIdentify" << endl;
//cout << "CCharsIdentify" << endl;
m_predictSize = 10;
m_path = "model/ann.xml";
LoadModel();

@ -7,12 +7,12 @@ namespace easypr{
CCharsRecognise::CCharsRecognise()
{
cout << "CCharsRecognise" << endl;
//cout << "CCharsRecognise" << endl;
m_charsSegment = new CCharsSegment();
m_charsIdentify = new CCharsIdentify();
}
void CCharsRecognise::LoadModel(string s)
void CCharsRecognise::LoadANN(string s)
{
m_charsIdentify->LoadModel(s.c_str());
}

@ -5,18 +5,21 @@
*/
namespace easypr{
#define HORIZONTAL 1
#define VERTICAL 0
const float DEFAULT_BLUEPERCEMT = 0.3;
const float DEFAULT_WHITEPERCEMT = 0.1;
CCharsSegment::CCharsSegment()
{
cout << "CCharsSegment" << endl;
m_NiuDingSize = 7;
m_theMatWidth = 136;
//cout << "CCharsSegment" << endl;
m_LiuDingSize = DEFAULT_LIUDING_SIZE;
m_theMatWidth = DEFAULT_MAT_WIDTH;
//!车牌颜色判断参数
m_ColorThreshold = DEFAULT_COLORTHRESHOLD;
m_BluePercent = DEFAULT_BLUEPERCEMT;
m_WhitePercent = DEFAULT_WHITEPERCEMT;
}
//! 字符尺寸验证
bool CCharsSegment::verifySizes(Mat r){
//Char sizes 45x90
@ -84,7 +87,7 @@ Mat CCharsSegment::histeq(Mat in)
//getPlateType
//判断车牌的类型1为蓝牌2为黄牌0为未知默认蓝牌
//通过像素中蓝色所占比例的多少来判断大于0.5为蓝牌,否则为黄牌
//通过像素中蓝色所占比例的多少来判断大于0.3为蓝牌,否则为黄牌
int CCharsSegment::getPlateType(Mat input)
{
Mat img;
@ -104,29 +107,23 @@ int CCharsSegment::getPlateType(Mat input)
int green = int(intensity.val[1]);
int red = int(intensity.val[2]);
if(blue > 150 && green > 10 && red > 10)
{
if(blue > m_ColorThreshold && green > 10 && red > 10)
countBlue++;
}
if(blue > 150 && green > 150 && red > 150)
{
if(blue > m_ColorThreshold && green > m_ColorThreshold && red > m_ColorThreshold)
countWhite++;
}
}
}
double percentBlue = countBlue/nums;
double percentWhite = countWhite/nums;
if (percentBlue - 0.3 > 0 && percentWhite - 0.1 > 0)
{
if (percentBlue - m_BluePercent > 0 && percentWhite - m_WhitePercent > 0)
return 1;
}
else
{
return 2;
}
return 0;
}
@ -136,7 +133,7 @@ int CCharsSegment::getPlateType(Mat input)
//X的推荐值为可根据实际调整
Mat CCharsSegment::clearLiuDing(Mat img)
{
const int x = m_NiuDingSize;
const int x = m_LiuDingSize;
Mat jump = Mat::zeros(1, img.rows, CV_32F);
for(int i=0; i < img.rows; i++)
{
@ -161,7 +158,7 @@ Mat CCharsSegment::clearLiuDing(Mat img)
return img;
}
//! 字符分割
//! 字符分割与排序
int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
{
if( !input.data )
@ -198,7 +195,9 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
vector<vector<Point> >::iterator itc= contours.begin();
vector<Rect> vecRect;
//Remove patch that are no inside limits of aspect ratio and area.
//Remove patch that are no inside limits of aspect ratio and area.
//将不符合特定尺寸的图块排除出去
while (itc != contours.end())
{
Rect mr = boundingRect(Mat(*itc));
@ -214,20 +213,27 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
return -1;
vector<Rect> sortedRect;
//对符合尺寸的图块按照从左到右进行排序
SortRect(vecRect, sortedRect);
int specIndex = 0;
//获得指示城市的特定Rect,如苏A的"A"
specIndex = GetSpecificRect(sortedRect);
//根据特定Rect向左反推出中文字符
//这样做的主要原因是根据findContours方法很难捕捉到中文字符的准确Rect因此仅能
//退过特定算法来指定
Rect chineseRect;
if (specIndex < sortedRect.size())
chineseRect = GetChineseRect(sortedRect[specIndex]);
else
return -1;
//新建一个全新的排序Rect
//将中文字符Rect第一个加进来因为它肯定是最左边的
//其余的Rect只按照顺序去6个车牌只可能是7个字符这样可以避免阴影导致的“1”字符
vector<Rect> newSortedRect;
newSortedRect.push_back(chineseRect);
RebuildRect(sortedRect, newSortedRect, specIndex);
if (newSortedRect.size() == 0)
@ -237,7 +243,6 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
{
Rect mr = newSortedRect[i];
Mat auxRoi(img_threshold, mr);
if (1)
{
auxRoi = preprocessChar(auxRoi);
@ -292,8 +297,6 @@ int CCharsSegment::SortRect(const vector<Rect>& vecRect, vector<Rect>& out)
return 0;
}
//! 根据特殊车牌来构造猜测中文字符的位置和大小
Rect CCharsSegment::GetChineseRect(const Rect rectSpe)
{
@ -310,7 +313,7 @@ Rect CCharsSegment::GetChineseRect(const Rect rectSpe)
return a;
}
//! 找出指示城市的字符的Rect例如苏A7003X就是A的位置
//! 找出指示城市的字符的Rect例如苏A7003X就是"A"的位置
int CCharsSegment::GetSpecificRect(const vector<Rect>& vecRect)
{
vector<int> xpositions;

@ -7,12 +7,12 @@ namespace easypr{
CPlateDetect::CPlateDetect()
{
cout << "CPlateDetect" << endl;
//cout << "CPlateDetect" << endl;
m_plateLocate = new CPlateLocate();
m_plateJudge = new CPlateJudge();
}
void CPlateDetect::LoadModel(string s)
void CPlateDetect::LoadSVM(string s)
{
m_plateJudge->LoadModel(s.c_str());
}

@ -7,7 +7,7 @@ namespace easypr{
CPlateJudge::CPlateJudge()
{
cout << "CPlateJudge" << endl;
//cout << "CPlateJudge" << endl;
m_path = "model/svm.xml";
LoadModel();
}

@ -5,19 +5,36 @@
*/
namespace easypr{
const float DEFAULT_ERROR = 0.6;
const float DEFAULT_ASPECT = 3.75;
CPlateLocate::CPlateLocate()
{
//cout << "CPlateLocate" << endl;
m_GaussianBlurSize = DEFAULT_GAUSSIANBLUR_SIZE;
m_MorphSizeWidth = DEFAULT_MORPH_SIZE_WIDTH;
m_MorphSizeHeight = DEFAULT_MORPH_SIZE_HEIGHT;
m_error = DEFAULT_ERROR;
m_aspect = DEFAULT_ASPECT;
m_verifyMin = DEFAULT_VERIFY_MIN;
m_verifyMax = DEFAULT_VERIFY_MAX;
m_angle = DEFAULT_ANGLE;
}
//! 对minAreaRect获得的最小外接矩形用纵横比进行判断
bool CPlateLocate::verifySizes(RotatedRect mr)
{
float error = 0.6;
float error = m_error;
//Spain car plate size: 52x11 aspect 4,7272
//China car plate size: 440mm*140mmaspect 3.142857
const float ASPECT = 3.75;
float aspect = ASPECT;
float aspect = m_aspect;
//Set a min and max area. All other patchs are discarded
//int min= 1*aspect*1; // minimum area
//int max= 2000*aspect*2000; // maximum area
int min= 44*14*3; // minimum area
int max= 44*14*20; // maximum area
int min= 44*14*m_verifyMin; // minimum area
int max= 44*14*m_verifyMax; // maximum area
//Get only patchs that match to a respect ratio.
float rmin= aspect-aspect*error;
float rmax= aspect+aspect*error;
@ -70,7 +87,8 @@ int CPlateLocate::plateLocate(Mat src, vector<Mat>& resultVec)
{ return -1; }
//高斯均衡。Size中的数字影响车牌定位的效果。
GaussianBlur( src, src_blur, Size(GAUSSIANBLUR_SIZE, GAUSSIANBLUR_SIZE), 0, 0, BORDER_DEFAULT );
GaussianBlur( src, src_blur, Size(m_GaussianBlurSize, m_GaussianBlurSize),
0, 0, BORDER_DEFAULT );
/// Convert it to gray
cvtColor( src_blur, src_gray, CV_RGB2GRAY );
@ -96,7 +114,7 @@ int CPlateLocate::plateLocate(Mat src, vector<Mat>& resultVec)
threshold(grad, img_threshold, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);
//threshold(grad, img_threshold, 75, 255, CV_THRESH_BINARY);
Mat element = getStructuringElement(MORPH_RECT, Size(MORPH_SIZE_WIDTH, MORPH_SIZE_HEIGHT) );
Mat element = getStructuringElement(MORPH_RECT, Size(m_MorphSizeWidth, m_MorphSizeHeight) );
morphologyEx(img_threshold, img_threshold, CV_MOP_CLOSE, element);
//Find 轮廓 of possibles plates
@ -148,8 +166,8 @@ int CPlateLocate::plateLocate(Mat src, vector<Mat>& resultVec)
angle = 90 + angle;
swap(rect_size.width, rect_size.height);
}
//如果抓取的方块旋转超过30角度,则不是车牌,放弃处理
if (angle - 30 < 0 && angle + 30 > 0)
//如果抓取的方块旋转超过m_angle角度,则不是车牌,放弃处理
if (angle - m_angle < 0 && angle + m_angle > 0)
{
//Create and rotate image
Mat rotmat = getRotationMatrix2D(minRect.center, angle, 1);
@ -166,9 +184,4 @@ int CPlateLocate::plateLocate(Mat src, vector<Mat>& resultVec)
return 0;
}
CPlateLocate::CPlateLocate()
{
cout << "CPlateLocate" << endl;
}
} /*! \namespace easypr*/

@ -7,51 +7,58 @@ namespace easypr{
CPlateRecognize::CPlateRecognize()
{
cout << "CPlateRecognize" << endl;
m_plateDetect= new CPlateDetect();
m_charsRecognise = new CCharsRecognise();
//cout << "CPlateRecognize" << endl;
//m_plateDetect= new CPlateDetect();
//m_charsRecognise = new CCharsRecognise();
}
//! ×°ÔØSVMÄ£ÐÍ
void CPlateRecognize::LoadSVM(string strSVM)
{
m_plateDetect->LoadModel(strSVM.c_str());
}
//! ×°ÔØANNÄ£ÐÍ
void CPlateRecognize::LoadANN(string strANN)
{
m_charsRecognise->LoadModel(strANN.c_str());
}
int CPlateRecognize::plateDetect(Mat src, vector<Mat>& resultVec)
{
int result = m_plateDetect->plateDetect(src, resultVec);
return result;
}
int CPlateRecognize::charsRecognise(Mat plate, string& plateLicense)
{
int result = m_charsRecognise->charsRecognise(plate, plateLicense);
return result;
}
////! ×°ÔØSVMÄ£ÐÍ
//void CPlateRecognize::LoadSVM(string strSVM)
//{
// m_plateDetect->LoadModel(strSVM.c_str());
//}
//
////! ×°ÔØANNÄ£ÐÍ
//void CPlateRecognize::LoadANN(string strANN)
//{
// m_charsRecognise->LoadModel(strANN.c_str());
//}
//
//int CPlateRecognize::plateDetect(Mat src, vector<Mat>& resultVec)
//{
// int result = m_plateDetect->plateDetect(src, resultVec);
// return result;
//}
//
//int CPlateRecognize::charsRecognise(Mat plate, string& plateLicense)
//{
// int result = m_charsRecognise->charsRecognise(plate, plateLicense);
// return result;
//}
int CPlateRecognize::plateRecognize(Mat src, vector<string>& plateVec)
int CPlateRecognize::plateRecognize(Mat src, vector<string>& licenseVec)
{
//车牌方块集合
vector<Mat> matVec;
vector<Mat> plateVec;
int resultPD = m_plateDetect->plateDetect(src, matVec);
int resultPD = plateDetect(src, plateVec);
if (resultPD == 0)
{
int num = matVec.size();
int num = plateVec.size();
for (int j = 0; j < num; j++)
{
Mat plate = plateVec[j];
//»ñÈ¡³µÅÆÑÕÉ«
string plateType = getPlateType(plate);
//»ñÈ¡³µÅƺÅ
string plateIdentify = "";
int resultCR = m_charsRecognise->charsRecognise(matVec[j], plateIdentify);
int resultCR = charsRecognise(plate, plateIdentify);
if (resultCR == 0)
{
plateVec.push_back(plateIdentify);
string license = plateType + ":" + plateIdentify;
licenseVec.push_back(license);
}
}
}

@ -25,10 +25,10 @@ int main()
{
assert (test_plate_locate() == 0);
assert (test_plate_judge() == 0);
assert (test_plate_detect() == 0);
assert (test_chars_segment() == 0);
assert (test_chars_identify() == 0);
assert (test_plate_detect() == 0);
assert (test_chars_recognise() == 0);
assert (test_plate_recognize() == 0);
@ -175,6 +175,7 @@ int test_chars_identify()
}
cout << "Identify Correct!" << endl;
cout << "Enter 1 for coninue:";
int a = 0;
cin >> a;
@ -222,6 +223,7 @@ int test_chars_recognise()
cout << "charsRecognise: " << charsRecognise << endl;
}
cout << "Enter 1 for coninue:";
int a = 0;
cin >> a;
@ -235,6 +237,18 @@ int test_plate_recognize()
Mat src = imread("image/plate_recognize.jpg");
CPlateRecognize pr;
pr.LoadANN("model/ann.xml");
pr.LoadSVM("model/svm.xml");
pr.setGaussianBlurSize(5);
pr.setMorphSizeWidth(17);
pr.setVerifyMin(3);
pr.setVerifyMax(20);
pr.setLiuDingSize(7);
pr.setColorThreshold(150);
vector<string> plateVec;
int result = pr.plateRecognize(src, plateVec);
@ -247,6 +261,7 @@ int test_plate_recognize()
}
}
cout << "Enter 1 for coninue:";
int a = 0;
cin >> a;

@ -30,7 +30,31 @@ public:
int charsRecognise(Mat, String&);
//! 装载ANN模型
void LoadModel(string s);
void LoadANN(string s);
//! »ñµÃ³µÅÆÑÕÉ«
inline string getPlateType(Mat input) const
{
string color = "δ֪";
int result = m_charsSegment->getPlateType(input);
if (1 == result)
{
color = "À¶ÅÆ";
}
if (2 == result)
{
color = "»ÆÅÆ";
}
return color;
}
//! ÉèÖñäÁ¿
inline void setLiuDingSize(int param){ m_charsSegment->setLiuDingSize(param);}
inline void setColorThreshold(int param){ m_charsSegment->setColorThreshold(param);}
inline void setBluePercent(float param){ m_charsSegment->setBluePercent(param);}
inline float getBluePercent() const { return m_charsSegment->getBluePercent();}
inline void setWhitePercent(float param){ m_charsSegment->setWhitePercent(param);}
inline float getWhitePercent() const { return m_charsSegment->getWhitePercent();}
private:
//!字符分割

@ -62,14 +62,36 @@ public:
//! 将Rect按位置从左到右进行排序
int SortRect(const vector<Rect>& vecRect, vector<Rect>& out);
//! 设置变量
inline void setLiuDingSize(int param){ m_LiuDingSize = param;}
inline void setColorThreshold(int param){ m_ColorThreshold = param;}
inline void setBluePercent(float param){ m_BluePercent = param;}
inline float getBluePercent() const { return m_BluePercent;}
inline void setWhitePercent(float param){ m_WhitePercent = param;}
inline float getWhitePercent() const { return m_WhitePercent;}
//! preprocessChar所用常量
static const int CHAR_SIZE = 20;
static const int HORIZONTAL = 1;
static const int VERTICAL = 0;
//! preprocessChar所用常量
static const int DEFAULT_LIUDING_SIZE = 7;
static const int DEFAULT_MAT_WIDTH = 136;
static const int DEFAULT_COLORTHRESHOLD = 150;
private:
int m_NiuDingSize;
//!柳钉判断参数
int m_LiuDingSize;
//!车牌大小参数
int m_theMatWidth;
//!车牌颜色判断参数
int m_ColorThreshold;
float m_BluePercent;
float m_WhitePercent;
};
} /* \namespace easypr */

@ -21,16 +21,36 @@
*/
namespace easypr {
class CPlateDetect
class CPlateDetect
{
public:
CPlateDetect();
//! ³µÅƶ¨Î»ÓëÅжÏ
//! 车牌检测:车牌定位与判断
int plateDetect(Mat, vector<Mat>&);
//! 装载SVM模型
void LoadModel(string s);
void LoadSVM(string s);
//! 设置与读取变量
inline void setGaussianBlurSize(int param){ m_plateLocate->setGaussianBlurSize(param);}
inline int getGaussianBlurSize() const{ return m_plateLocate->getGaussianBlurSize();}
inline void setMorphSizeWidth(int param){m_plateLocate->setMorphSizeWidth(param);}
inline int getMorphSizeWidth() const{return m_plateLocate->getMorphSizeWidth();}
inline void setMorphSizeHeight(int param){m_plateLocate->setMorphSizeHeight(param);}
inline int getMorphSizeHeight() const{return m_plateLocate->getMorphSizeHeight();}
inline void setVerifyError(float param){m_plateLocate->setVerifyError(param);}
inline float getVerifyError() const { return m_plateLocate->getVerifyError();}
inline void setVerifyAspect(float param){m_plateLocate->setVerifyAspect(param);}
inline float getVerifyAspect() const { return m_plateLocate->getVerifyAspect();}
inline void setVerifyMin(int param){m_plateLocate->setVerifyMin(param);}
inline void setVerifyMax(int param){m_plateLocate->setVerifyMax(param);}
inline void setJudgeAngle(int param){m_plateLocate->setJudgeAngle(param);}
private:
//!车牌定位

@ -2,6 +2,7 @@
// Name: plate_locate Header
// Version: 1.0
// Date: 2014-09-19
// MDate: 2014-09-29
// Author: liuruoze
// Copyright: liuruoze
// Reference: Mastering OpenCV with Practical Computer Vision Projects
@ -33,20 +34,64 @@ public:
//! ½á¹û³µÅÆÏÔʾ
Mat showResultMat(Mat src, Size rect_size, Point2f center);
//! PlateDection所用常量
static const int GAUSSIANBLUR_SIZE = 5;
//! 设置与读取变量
inline void setGaussianBlurSize(int param){ m_GaussianBlurSize = param;}
inline int getGaussianBlurSize() const{ return m_GaussianBlurSize;}
inline void setMorphSizeWidth(int param){ m_MorphSizeWidth = param;}
inline int getMorphSizeWidth() const{ return m_MorphSizeWidth;}
inline void setMorphSizeHeight(int param){ m_MorphSizeHeight = param;}
inline int getMorphSizeHeight() const{ return m_MorphSizeHeight;}
inline void setVerifyError(float param){ m_error = param;}
inline float getVerifyError() const { return m_error;}
inline void setVerifyAspect(float param){ m_aspect = param;}
inline float getVerifyAspect() const { return m_aspect;}
inline void setVerifyMin(int param){ m_verifyMin = param;}
inline void setVerifyMax(int param){ m_verifyMax = param;}
inline void setJudgeAngle(int param){ m_angle = param;}
//! PlateLocate所用常量
static const int DEFAULT_GAUSSIANBLUR_SIZE = 5;
static const int SOBEL_SCALE = 1;
static const int SOBEL_DELTA = 0;
static const int SOBEL_DDEPTH = CV_16S;
static const int SOBEL_X_WEIGHT = 1;
static const int SOBEL_Y_WEIGHT = 0;
static const int MORPH_SIZE_WIDTH = 17;
static const int MORPH_SIZE_HEIGHT = 3;
static const int DEFAULT_MORPH_SIZE_WIDTH = 17;
static const int DEFAULT_MORPH_SIZE_HEIGHT = 3;
//! showResultMatËùÓó£Á¿
static const int WIDTH = 136;
static const int HEIGHT = 36;
static const int TYPE = CV_8UC3;
//! verifySize所用常量
static const int DEFAULT_VERIFY_MIN = 3;
static const int DEFAULT_VERIFY_MAX = 20;
//! 角度判断所用常量
static const int DEFAULT_ANGLE = 30;
protected:
//! 高斯模糊所用变量
int m_GaussianBlurSize;
//! 连接操作所用变量
int m_MorphSizeWidth;
int m_MorphSizeHeight;
//! verifySize所用变量
float m_error;
float m_aspect;
int m_verifyMin;
int m_verifyMax;
//! 角度判断所用变量
int m_angle;
};
} /*! \namespace easypr*/

@ -21,32 +21,32 @@
*/
namespace easypr {
class CPlateRecognize
class CPlateRecognize : public CPlateDetect, public CCharsRecognise
{
public:
CPlateRecognize();
//! ³µÅƼì²âÓë×Ö·ûʶ±ð
int plateRecognize(Mat, vector<string>& );
int plateRecognize(Mat, vector<string>&);
//! 车牌定位与判断
int plateDetect(Mat, vector<Mat>&);
////! 车牌定位与判断
//int plateDetect(Mat, vector<Mat>&);
//! 字符分割与识别
int charsRecognise(Mat, String&);
////! 字符分割与识别
//int charsRecognise(Mat, String&);
//! 装载SVM
void LoadSVM(string s);
////! 装载SVM
//void LoadSVM(string s);
//! 装载ANN模型
void LoadANN(string s);
////! 装载ANN模型
//void LoadANN(string s);
private:
//!车牌检测
CPlateDetect* m_plateDetect;
////!车牌检测
//CPlateDetect* m_plateDetect;
//! 字符识别
CCharsRecognise* m_charsRecognise;
////! 字符识别
//CCharsRecognise* m_charsRecognise;
};
} /* \namespace easypr */

Loading…
Cancel
Save