add LoadModel, maxPlates

v1.6alpha
liuruoze 9 years ago
parent 285fdc03b0
commit 68fc98414c

@ -1561,3 +1561,23 @@
总图片数:200, 未识出图片:7, 定位率:96.5% 总图片数:200, 未识出图片:7, 定位率:96.5%
平均字符差距:0.689119, 完全匹配数:132, 完全匹配率:68.3938% 平均字符差距:0.689119, 完全匹配数:132, 完全匹配率:68.3938%
总时间:330秒, 平均执行时间:1.65秒 总时间:330秒, 平均执行时间:1.65秒
2016-06-15 19:58:37
总图片数:200, 未识出图片:7, 定位率:96.5%
平均字符差距:0.689119, 完全匹配数:132, 完全匹配率:68.3938%
总时间:181秒, 平均执行时间:0.905秒
2016-06-15 20:13:59
总图片数:200, 未识出图片:7, 定位率:96.5%
平均字符差距:0.689119, 完全匹配数:132, 完全匹配率:68.3938%
总时间:181秒, 平均执行时间:0.905秒
2016-06-15 21:05:45
总图片数:50, 未识出图片:26, 定位率:48%
平均字符差距:2.45833, 完全匹配数:6, 完全匹配率:25%
总时间:456秒, 平均执行时间:9.12秒
2016-06-15 21:25:41
总图片数:200, 未识出图片:7, 定位率:96.5%
平均字符差距:0.689119, 完全匹配数:132, 完全匹配率:68.3938%
总时间:186秒, 平均执行时间:0.93秒
2016-06-15 21:51:53
总图片数:50, 未识出图片:18, 定位率:64%
平均字符差距:0, 完全匹配数:0, 完全匹配率:0%
总时间:273秒, 平均执行时间:5.46秒

@ -16,6 +16,8 @@ class CharsIdentify {
std::pair<std::string, std::string> identify(cv::Mat input, bool isChinese = false); std::pair<std::string, std::string> identify(cv::Mat input, bool isChinese = false);
bool isCharacter(cv::Mat input, std::string& label, float& maxVal, bool isChinese = false); bool isCharacter(cv::Mat input, std::string& label, float& maxVal, bool isChinese = false);
void LoadModel(std::string path);
private: private:
CharsIdentify(); CharsIdentify();

@ -14,6 +14,13 @@ enum Color { BLUE, YELLOW, WHITE, UNKNOWN };
enum LocateType { SOBEL, COLOR, CMSER, OTHER }; enum LocateType { SOBEL, COLOR, CMSER, OTHER };
enum
{
PR_DETECT_SOBEL = 0x01, /**Sobel detect typeusing twice Sobel */
PR_DETECT_COLOR = 0x02, /**Color detect type */
PR_DETECT_CMSER = 0x04, /**Character detect typeusing mser */
};
//! 根据一幅图像与颜色模板获取对应的二值图 //! 根据一幅图像与颜色模板获取对应的二值图
//! 输入RGB图像, 颜色模板(蓝色、黄色) //! 输入RGB图像, 颜色模板(蓝色、黄色)
//! 输出灰度图只有0和255两个值255代表匹配0代表不匹配 //! 输出灰度图只有0和255两个值255代表匹配0代表不匹配

@ -12,13 +12,6 @@ class CPlateDetect {
~CPlateDetect(); ~CPlateDetect();
enum
{
PR_DETECT_SOBEL = 0x01, /**Sobel detect typeusing twice Sobel */
PR_DETECT_COLOR = 0x02, /**Color detect type */
PR_DETECT_CMSER = 0x04, /**Character detect typeusing mser */
};
/** @brief Plate detect in an image. /** @brief Plate detect in an image.
The function detects plate in an image. It can use sobel, color, and character method or the combinations of them. The function detects plate in an image. It can use sobel, color, and character method or the combinations of them.
@ -29,9 +22,24 @@ class CPlateDetect {
@param showDetectArea @param showDetectArea
@param index @param index
*/ */
int plateDetect(Mat src, std::vector<CPlate> &resultVec, int type = 0, int plateDetect(Mat src, std::vector<CPlate> &resultVec, int type,
bool showDetectArea = true, int index = 0); bool showDetectArea = true, int index = 0);
/** @brief Plate detect in an image.
The function detects plate in an image. It can use sobel, color, and character method or the combinations of them.
Use default m_type, it can use setDetectType() to set it;
@param src Source image.
@param resultVec Destination vector of CPlate.
@param showDetectArea
@param index
*/
int plateDetect(Mat src, std::vector<CPlate> &resultVec,
bool showDetectArea = true, int index = 0);
//! 展示中间的结果 //! 展示中间的结果
int showResult(const Mat &result); int showResult(const Mat &result);
@ -52,6 +60,9 @@ class CPlateDetect {
inline bool getPDDebug() { return m_plateLocate->getDebug(); } inline bool getPDDebug() { return m_plateLocate->getDebug(); }
inline void setDetectType(int param) { m_type = param; }
//! 设置与读取变量 //! 设置与读取变量
inline void setGaussianBlurSize(int param) { inline void setGaussianBlurSize(int param) {
@ -113,6 +124,11 @@ class CPlateDetect {
//! 车牌定位 //! 车牌定位
CPlateLocate* m_plateLocate; CPlateLocate* m_plateLocate;
int m_type;
static std::string m_pathSvm;
}; };
} }

@ -13,8 +13,10 @@ class PlateJudge {
//! 对多幅车牌进行SVM判断 //! 对多幅车牌进行SVM判断
void LoadModel(std::string path);
int plateJudge(const std::vector<CPlate> &, std::vector<CPlate> &); int plateJudge(const std::vector<CPlate> &, std::vector<CPlate> &);
int plateJudgeUsingNMS(const std::vector<CPlate> &, std::vector<CPlate> &); int plateJudgeUsingNMS(const std::vector<CPlate> &, std::vector<CPlate> &, int maxPlates = 5);
//! 车牌判断 //! 车牌判断

@ -38,6 +38,9 @@ namespace easypr {
//! 是否开启调试模式 //! 是否开启调试模式
inline void setDebug(bool param) { CPlateDetect::setPDDebug(param); } inline void setDebug(bool param) { CPlateDetect::setPDDebug(param); }
inline void setDetectType(int param) { CPlateDetect::setDetectType(param); }
}; };
} /* \namespace easypr */ } /* \namespace easypr */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 323 KiB

File diff suppressed because it is too large Load Diff

@ -19,6 +19,11 @@ namespace easypr {
kv_->load("etc/province_mapping"); kv_->load("etc/province_mapping");
} }
void CharsIdentify::LoadModel(std::string path) {
ann_->clear();
ann_->ml::ANN_MLP::load<ml::ANN_MLP>(path);
}
int CharsIdentify::classify(cv::Mat f, float& maxVal, bool isChinses){ int CharsIdentify::classify(cv::Mat f, float& maxVal, bool isChinses){
int result = -1; int result = -1;

@ -803,11 +803,11 @@ Mat preprocessChar(Mat in, int char_size) {
Rect GetChineseRect(const Rect rectSpe) { Rect GetChineseRect(const Rect rectSpe) {
int height = rectSpe.height; int height = rectSpe.height;
float newwidth = rectSpe.width * 1.2f; float newwidth = rectSpe.width * 1.10f;
int x = rectSpe.x; int x = rectSpe.x;
int y = rectSpe.y; int y = rectSpe.y;
int newx = x - int(newwidth * 1.2); int newx = x - int(newwidth * 1.10f);
newx = newx > 0 ? newx : 0; newx = newx > 0 ? newx : 0;
Rect a(newx, y, int(newwidth), height); Rect a(newx, y, int(newwidth), height);
@ -1007,14 +1007,14 @@ Mat mserMatch(const Mat &src, Mat &match, const Color r,
if (verifyCharSizes(rect)) { if (verifyCharSizes(rect)) {
float aspect = float(rect.width) / float(rect.height); float aspect = float(rect.width) / float(rect.height);
Mat region = image(rect); //Mat region = image(rect);
Mat binary_region; //Mat binary_region;
threshold(region, binary_region, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); //threshold(region, binary_region, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
Mat charInput = preprocessChar(binary_region, 20); //Mat charInput = preprocessChar(binary_region, 20);
std::string label = ""; //std::string label = "";
float maxVal = -2.f; //float maxVal = -2.f;
bool isCharacter = CharsIdentify::instance()->isCharacter(charInput, label, maxVal); //bool isCharacter = CharsIdentify::instance()->isCharacter(charInput, label, maxVal);
if (1) { if (1) {
//match(rect) = min(max(0, int(maxVal * 255)),255); //match(rect) = min(max(0, int(maxVal * 255)),255);

@ -6,9 +6,8 @@ namespace easypr {
CPlateDetect::CPlateDetect() { CPlateDetect::CPlateDetect() {
m_plateLocate = new CPlateLocate(); m_plateLocate = new CPlateLocate();
// 默认EasyPR在一幅图中定位最多3个车
m_maxPlates = 3; m_maxPlates = 3;
m_type = 0;
} }
CPlateDetect::~CPlateDetect() { SAFE_RELEASE(m_plateLocate); } CPlateDetect::~CPlateDetect() { SAFE_RELEASE(m_plateLocate); }
@ -54,7 +53,7 @@ namespace easypr {
} }
} }
if (!type || type & PR_DETECT_CMSER) if ( !type || type & PR_DETECT_CMSER)
{ {
m_plateLocate->plateMserLocate(src, mser_Plates, index); m_plateLocate->plateMserLocate(src, mser_Plates, index);
@ -69,13 +68,18 @@ namespace easypr {
} }
} }
// 使用非极大值抑制来判断车牌 // 使用非极大值抑制来判断车牌
PlateJudge::instance()->plateJudgeUsingNMS(all_result_Plates, resultVec); PlateJudge::instance()->plateJudgeUsingNMS(all_result_Plates, resultVec, m_maxPlates);
return 0; return 0;
} }
int CPlateDetect::plateDetect(Mat src, std::vector<CPlate> &resultVec,
bool showDetectArea, int index) {
int result = plateDetect(src, resultVec, m_type, showDetectArea, index);
return result;
}
int CPlateDetect::showResult(const Mat &result) { int CPlateDetect::showResult(const Mat &result) {
namedWindow("EasyPR", CV_WINDOW_AUTOSIZE); namedWindow("EasyPR", CV_WINDOW_AUTOSIZE);

@ -14,6 +14,11 @@ namespace easypr {
PlateJudge::PlateJudge() { svm_ = ml::SVM::load<ml::SVM>(kDefaultSvmPath); } PlateJudge::PlateJudge() { svm_ = ml::SVM::load<ml::SVM>(kDefaultSvmPath); }
void PlateJudge::LoadModel(std::string path) {
svm_->clear();
svm_->ml::SVM::load<ml::SVM>(path);
}
//! 对单幅图像进行SVM判断 //! 对单幅图像进行SVM判断
int PlateJudge::plateJudge(const Mat &inMat, int &result) { int PlateJudge::plateJudge(const Mat &inMat, int &result) {
@ -98,7 +103,7 @@ namespace easypr {
} }
//! 使用非极大值抑制的车牌判断 //! 使用非极大值抑制的车牌判断
int PlateJudge::plateJudgeUsingNMS(const std::vector<CPlate> &inVec, std::vector<CPlate> &resultVec) { int PlateJudge::plateJudgeUsingNMS(const std::vector<CPlate> &inVec, std::vector<CPlate> &resultVec, int maxPlates) {
std::vector<CPlate> plateVec; std::vector<CPlate> plateVec;
int num = inVec.size(); int num = inVec.size();
@ -139,10 +144,22 @@ namespace easypr {
} }
} }
std::vector<CPlate> reDupPlateVec;
// 使用非极大值抑制来去除那些重叠的车牌 // 使用非极大值抑制来去除那些重叠的车牌
// overlap阈值设置为0.5 // overlap阈值设置为0.5
double overlap = 0.5; double overlap = 0.5;
NMS(plateVec, resultVec, overlap); NMS(plateVec, reDupPlateVec, overlap);
std::vector<CPlate>::iterator it = reDupPlateVec.begin();
int count = 0;
for (; it != reDupPlateVec.end(); ++it) {
resultVec.push_back(*it);
count++;
if (count >= maxPlates)
break;
}
return 0; return 0;
} }

@ -87,7 +87,7 @@ int CPlateLocate::mserSearch(const Mat &src, const Color r, Mat &out,
// width值对最终结果影响很大可以考虑进行多次colorSerch每次不同的值 // width值对最终结果影响很大可以考虑进行多次colorSerch每次不同的值
// 另一种解决方案就是在结果输出到SVM之前进行线与角的再纠正 // 另一种解决方案就是在结果输出到SVM之前进行线与角的再纠正
const int color_morph_width = 20; const int color_morph_width = 30;
const int color_morph_height = 5; const int color_morph_height = 5;
std::vector<RotatedRect> plateRects; std::vector<RotatedRect> plateRects;
@ -550,6 +550,10 @@ int CPlateLocate::deskew(const Mat &src, const Mat &src_b,
Scalar(0, 255, 255), 1, 8); Scalar(0, 255, 255), 1, 8);
} }
// changed
// rotation = 90 - abs(roi_angle);
// rotation < m_angel;
// m_angle=60 // m_angle=60
if (roi_angle - m_angle < 0 && roi_angle + m_angle > 0) { if (roi_angle - m_angle < 0 && roi_angle + m_angle > 0) {
Rect_<float> safeBoundRect; Rect_<float> safeBoundRect;
@ -595,7 +599,6 @@ int CPlateLocate::deskew(const Mat &src, const Mat &src_b,
plate_mat.create(HEIGHT, WIDTH, TYPE); plate_mat.create(HEIGHT, WIDTH, TYPE);
// haitungaga添加删除非区域这个函数影响了25%的完整定位率 // haitungaga添加删除非区域这个函数影响了25%的完整定位率
DeleteNotArea(deskew_mat); DeleteNotArea(deskew_mat);
// 这里对deskew_mat进行了一个筛选 // 这里对deskew_mat进行了一个筛选
@ -615,6 +618,12 @@ int CPlateLocate::deskew(const Mat &src, const Mat &src_b,
CPlate plate; CPlate plate;
plate.setPlatePos(roi_rect); plate.setPlatePos(roi_rect);
plate.setPlateMat(plate_mat); plate.setPlateMat(plate_mat);
if (0) {
imshow("plate_mat", plate_mat);
waitKey(0);
}
outPlates.push_back(plate); outPlates.push_back(plate);
} }
} }

@ -248,19 +248,20 @@ namespace easypr {
// 对图像进行统一缩放,确保图像不要过大 // 对图像进行统一缩放,确保图像不要过大
// 对速度提升帮助不大 // 对速度提升帮助不大
int scale_size = 1600; int scale_size = 1200;
double scale_ratio = 1; double scale_ratio = 1;
Mat image = scaleImage(channelImage, Size(scale_size, scale_size), scale_ratio); Mat image = scaleImage(channelImage, Size(scale_size, scale_size), scale_ratio);
Mat result = image; Mat result = image;
cvtColor(result, result, COLOR_GRAY2BGR); cvtColor(result, result, COLOR_GRAY2BGR);
int imageArea = image.rows * image.cols; int imageArea = image.rows * image.cols;
if (3 == flags[i]) { if (3 == flags[i]) {
mser = MSER::create(3, 30, int(0.25 * imageArea)); mser = MSER::create(3, 30, int(0.05 * imageArea));
} }
else { else {
mser = MSER::create(1, 30, int(0.25 * imageArea)); mser = MSER::create(1, 30, int(0.05 * imageArea));
} }
mser->detectRegions(image, all_contours[i], all_boxes[i]); mser->detectRegions(image, all_contours[i], all_boxes[i]);
@ -399,7 +400,7 @@ namespace easypr {
//src = ret; //src = ret;
// 进行深度定位使用颜色信息与二次Sobel // 进行深度定位使用颜色信息与二次Sobel
int resultPD = plateDetect(src, plateVec, CPlateDetect::PR_DETECT_SOBEL | CPlateDetect::PR_DETECT_COLOR); int resultPD = plateDetect(src, plateVec);
if (resultPD == 0) { if (resultPD == 0) {
size_t num = plateVec.size(); size_t num = plateVec.size();

@ -91,6 +91,9 @@ namespace easypr {
pr.setMaxPlates(4); pr.setMaxPlates(4);
//pr.setDetectType(PR_DETECT_COLOR | PR_DETECT_SOBEL);
pr.setDetectType(PR_DETECT_CMSER);
int size = files.size(); int size = files.size();
if (0 == size) { if (0 == size) {

@ -110,12 +110,13 @@ int test_plate_recognize() {
CPlateRecognize pr; CPlateRecognize pr;
pr.setLifemode(true); pr.setLifemode(true);
pr.setDebug(true); pr.setDebug(true);
pr.setDetectType(easypr::PR_DETECT_CMSER);
//vector<string> plateVec; //vector<string> plateVec;
vector<CPlate> plateVec; vector<CPlate> plateVec;
int result = pr.plateRecognize(src, plateVec); //int result = pr.plateRecognize(src, plateVec);
//int result = pr.plateRecognizeAsText(src, plateVec); int result = pr.plateRecognizeAsText(src, plateVec);
if (result == 0) { if (result == 0) {
size_t num = plateVec.size(); size_t num = plateVec.size();
for (size_t j = 0; j < num; j++) { for (size_t j = 0; j < num; j++) {

Loading…
Cancel
Save