* add adpative to charRect and ann model for only chinese.

v1.6alpha
liuruoze 9 years ago
parent 725262aa5f
commit dc5e669e92

@ -1767,3 +1767,13 @@ Recall:0%, Precise:0%, Fscore:0%.
Recall:0%, Precise:0%, Fscore:0%.
平均字符差距:0, 完全匹配数:0, 完全匹配率:0%
总时间:151秒, 平均执行时间:6.04秒
2016-06-24 21:09:30
总图片数:200, 未识出图片:6, 定位率:97%
Recall:83.2984%, Precise:86.2716%, Fscore:84.7589%.
平均字符差距:0.845361, 完全匹配数:127, 完全匹配率:65.4639%
总时间:214秒, 平均执行时间:1.07秒
2016-06-24 21:18:54
总图片数:200, 未识出图片:6, 定位率:97%
Recall:83.2984%, Precise:86.2716%, Fscore:84.7589%.
平均字符差距:0.958763, 完全匹配数:119, 完全匹配率:61.3402%
总时间:212秒, 平均执行时间:1.06秒

@ -46,6 +46,7 @@ static const char *kChars[] = {
};
static const int kCharactersNumber = 34;
static const int kChineseNumber = 31;
static const int kCharsTotalNumber = 65;
static bool kDebug = false;

@ -101,6 +101,9 @@ Mat adaptive_image_from_points(const std::vector<Point>& points,
const Rect& rect, const Size& size, const Scalar& backgroundColor = Scalar(0, 0, 0),
const Scalar& forgroundColor = Scalar(255, 255, 255), bool gray = true);
// Calculate a rect have same length and width and remains the center
Rect adaptive_charrect_from_rect(const Rect& rect);
//! 计算一个安全的Rect
bool calcSafeRect(const RotatedRect& roi_rect, const Mat& src,
Rect_<float>& safeBoundRect);

@ -19,6 +19,8 @@ class AnnTrain : public ITrain {
cv::Ptr<cv::ml::ANN_MLP> ann_;
const char* ann_xml_;
const char* chars_folder_;
int type;
};
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1338,9 +1338,11 @@ Mat mserCharMatch(const Mat &src, Mat &match, std::vector<Rect>& out_charRect, C
Mat charInput = preprocessChar(mserMat, char_size);
//cv::rectangle(result, rect, Scalar(0, 255, 0), 1);
//Rect charRect = adaptive_charrect_from_rect(rect);
Rect charRect = rect;
CCharacter charCandidate;
charCandidate.setCharacterPos(rect);
charCandidate.setCharacterPos(charRect);
charCandidate.setCharacterMat(charInput);
charCandidate.setIsChinese(false);
charVec.push_back(charCandidate);
@ -1399,11 +1401,14 @@ Mat mserCharMatch(const Mat &src, Mat &match, std::vector<Rect>& out_charRect, C
std::vector<CCharacter> mserCharVec;
for (auto character : charGroup) {
Rect charRect = character.getCharacterPos();
cv::rectangle(result, charRect, Scalar(0, 255, 0), 1);
plateResult |= charRect;
Point center(charRect.tl().x + charRect.width / 2, charRect.tl().y + charRect.height / 2);
points.push_back(center);
mserCharVec.push_back(character);
cv::circle(result, center, 3, Scalar(0, 255, 0), 2);
if (charRect.area() > maxarea) {
maxrect = charRect;
maxarea = charRect.area();
@ -1529,7 +1534,7 @@ Mat mserCharMatch(const Mat &src, Mat &match, std::vector<Rect>& out_charRect, C
slideWindowSearch(image, slideRightWindow, line, rightPoint, dist, maxrect, plateResult, CharSearchDirection::RIGHT, false);
std::cout << "slideRightWindow:" << slideRightWindow.size() << std::endl;
for (auto seed : slideRightWindow) {
cv::rectangle(result, seed.getCharacterPos(), Scalar(0, 255, 0), 1);
cv::rectangle(result, seed.getCharacterPos(), Scalar(0, 0, 255), 1);
mserCharacter.push_back(seed);
}
@ -1540,6 +1545,7 @@ Mat mserCharMatch(const Mat &src, Mat &match, std::vector<Rect>& out_charRect, C
searchWeakSeed(searchCandidate, searchLeftWeakSeed, line, leftPoint, maxrect, plateResult, CharSearchDirection::LEFT);
std::cout << "searchLeftWeakSeed:" << searchLeftWeakSeed.size() << std::endl;
for (auto seed : searchLeftWeakSeed) {
cv::rectangle(result, seed.getCharacterPos(), Scalar(255, 0, 0), 1);
mserCharacter.push_back(seed);
}
}
@ -1555,15 +1561,18 @@ Mat mserCharMatch(const Mat &src, Mat &match, std::vector<Rect>& out_charRect, C
});
CCharacter leftChar = mserCharacter[0];
//Rect theRect = adaptive_rect_from_rect(leftChar.getCharacterPos());
Rect theRect = leftChar.getCharacterPos();
cv::rectangle(result, theRect, Scalar(255, 0, 0), 1);
//cv::rectangle(result, theRect, Scalar(255, 0, 0), 1);
Mat region = image(theRect);
Mat binary_region;
threshold(region, binary_region, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
Mat charInput = preprocessChar(binary_region, 20);
if (0) {
if (1) {
imshow("charInput", charInput);
waitKey(0);
destroyWindow("charInput");
@ -1580,58 +1589,67 @@ Mat mserCharMatch(const Mat &src, Mat &match, std::vector<Rect>& out_charRect, C
//search for sliding window
if (!leftIsChinese) {
std::cout << "search for sliding window:" << std::endl;
int slideLength = int(1.25 * maxrect.width);
int slideStep = 1;
int fromX = leftPoint.x - maxrect.width / 2;
std::vector<CCharacter> chineseCandidate;
for (int slideX = 0; slideX < slideLength; slideX += slideStep) {
float x_slide = float(fromX - slideX);
float y_slide = k * (x_slide - x_1) + y_1;
Point2f p_slide(x_slide, y_slide);
//cv::circle(result, p_slide, 2, Scalar(0, 0, 255), 1);
int chineseWidth = int(maxrect.width * 1.05);
int chineseHeight = int(maxrect.height * 1.05);
Rect rect(Point2f(x_slide - chineseWidth / 2, y_slide - chineseHeight / 2), Size(chineseWidth, chineseHeight));
//cv::rectangle(result, rect, Scalar(0, 0, 255), 1);
if (rect.tl().x < 0 || rect.tl().y < 0 || rect.br().x >= image.cols || rect.br().y >= image.rows)
continue;
Mat region = image(rect);
Mat binary_region;
threshold(region, binary_region, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
Mat charInput = preprocessChar(binary_region, 20);
slideWindowSearch(image, slideLeftWindow, line, leftPoint, dist, maxrect, plateResult, CharSearchDirection::LEFT, true);
std::cout << "slideLeftWindow:" << slideLeftWindow.size() << std::endl;
for (auto seed : slideLeftWindow) {
cv::rectangle(result, seed.getCharacterPos(), Scalar(0, 0, 255), 1);
mserCharacter.push_back(seed);
}
//std::cout << "search for sliding window:" << std::endl;
//int slideLength = int(1.25 * maxrect.width);
//int slideStep = 1;
//int fromX = leftPoint.x - maxrect.width / 2;
//std::vector<CCharacter> chineseCandidate;
//for (int slideX = 0; slideX < slideLength; slideX += slideStep) {
// float x_slide = float(fromX - slideX);
// float y_slide = k * (x_slide - x_1) + y_1;
// Point2f p_slide(x_slide, y_slide);
// //cv::circle(result, p_slide, 2, Scalar(0, 0, 255), 1);
// int chineseWidth = int(maxrect.width * 1.05);
// int chineseHeight = int(maxrect.height * 1.05);
// Rect rect(Point2f(x_slide - chineseWidth / 2, y_slide - chineseHeight / 2), Size(chineseWidth, chineseHeight));
// //cv::rectangle(result, rect, Scalar(0, 0, 255), 1);
// if (rect.tl().x < 0 || rect.tl().y < 0 || rect.br().x >= image.cols || rect.br().y >= image.rows)
// continue;
// Mat region = image(rect);
// Mat binary_region;
// threshold(region, binary_region, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
// Mat charInput = preprocessChar(binary_region, 20);
// if (0) {
// imshow("charInput", charInput);
// waitKey(0);
// destroyWindow("charInput");
// }
// CCharacter charCandidate;
// charCandidate.setCharacterPos(rect);
// charCandidate.setCharacterMat(charInput);
// charCandidate.setIsChinese(true);
// chineseCandidate.push_back(charCandidate);
//}
if (0) {
imshow("charInput", charInput);
waitKey(0);
destroyWindow("charInput");
}
//CharsIdentify::instance()->classify(chineseCandidate);
//double overlapThresh = 0.1;
//NMStoCharacter(chineseCandidate, overlapThresh);
//for (auto chinese : chineseCandidate) {
// Rect rect = chinese.getCharacterPos();
// if (chinese.getCharacterScore() > 0.5) {
// cv::rectangle(result, rect, Scalar(0, 0, 255), 1);
// plateResult |= rect;
// std::cout << "chinese:" << chinese.getCharacterStr();
// std::cout << "__score:" << chinese.getCharacterScore() << std::endl;
// }
//}
CCharacter charCandidate;
charCandidate.setCharacterPos(rect);
charCandidate.setCharacterMat(charInput);
charCandidate.setIsChinese(true);
chineseCandidate.push_back(charCandidate);
}
CharsIdentify::instance()->classify(chineseCandidate);
double overlapThresh = 0.1;
NMStoCharacter(chineseCandidate, overlapThresh);
for (auto chinese : chineseCandidate) {
Rect rect = chinese.getCharacterPos();
if (chinese.getCharacterScore() > 0.5) {
cv::rectangle(result, rect, Scalar(255, 255, 255), 1);
plateResult |= rect;
std::cout << "chinese:" << chinese.getCharacterStr();
std::cout << "__score:" << chinese.getCharacterScore() << std::endl;
}
}
}
}
@ -1833,6 +1851,19 @@ void setPoint(Mat& mat, int row, int col, const Scalar& value) {
}
}
Rect adaptive_charrect_from_rect(const Rect& rect) {
int expendWidth = 0;
if (rect.height > 3 * rect.width) {
expendWidth = (rect.height / 2 - rect.width) / 2;
}
Rect resultRect(rect.tl().x - expendWidth, rect.tl().y,
rect.width + expendWidth * 2, rect.height);
return resultRect;
}
Mat adaptive_image_from_points(const std::vector<Point>& points,
const Rect& rect, const Size& size, const Scalar& backgroundColor /* = ml_color_white */,

@ -9,14 +9,19 @@ namespace easypr {
AnnTrain::AnnTrain(const char* chars_folder, const char* xml)
: chars_folder_(chars_folder), ann_xml_(xml) {
ann_ = cv::ml::ANN_MLP::create();
type = 0;
}
void AnnTrain::train() {
int classNumber = 0;
if (type == 0) classNumber = kCharsTotalNumber;
if (type == 1) classNumber = kChineseNumber;
cv::Mat layers(1, 3, CV_32SC1);
layers.at<int>(0) = 120; // the input layer
layers.at<int>(1) = kNeurons; // the neurons
layers.at<int>(2) = kCharsTotalNumber; // the output layer
layers.at<int>(2) = classNumber; // the output layer
ann_->setLayerSizes(layers);
ann_->setActivationFunction(cv::ml::ANN_MLP::SIGMOID_SYM, 1, 1);
ann_->setTrainMethod(cv::ml::ANN_MLP::TrainingMethods::BACKPROP);
@ -33,6 +38,8 @@ void AnnTrain::train() {
ann_->save(ann_xml_);
std::cout << "Your ANN Model was saved to " << ann_xml_ << std::endl;
//test();
}
void AnnTrain::test() {
@ -90,8 +97,12 @@ cv::Ptr<cv::ml::TrainData> AnnTrain::tdata() {
std::cout << "Collecting chars in " << chars_folder_ << std::endl;
for (int i = 0; i < kCharsTotalNumber; ++i) {
auto char_key = kChars[i];
int classNumber = 0;
if (type == 0) classNumber = kCharsTotalNumber;
if (type == 1) classNumber = kChineseNumber;
for (int i = 0; i < classNumber; ++i) {
auto char_key = kChars[i + kCharsTotalNumber - classNumber];
char sub_folder[512] = {0};
sprintf(sub_folder, "%s/%s", chars_folder_, char_key);
@ -111,7 +122,7 @@ cv::Ptr<cv::ml::TrainData> AnnTrain::tdata() {
cv::Mat samples_;
samples.convertTo(samples_, CV_32F);
cv::Mat train_classes =
cv::Mat::zeros((int)labels.size(), kCharsTotalNumber, CV_32F);
cv::Mat::zeros((int)labels.size(), classNumber, CV_32F);
for (int i = 0; i < train_classes.rows; ++i) {
train_classes.at<float>(i, labels[i]) = 1.f;

@ -97,8 +97,8 @@ namespace easypr {
// 设置要处理的一张图片中最多有多少车牌
pr.setMaxPlates(4);
//pr.setDetectType(PR_DETECT_COLOR | PR_DETECT_SOBEL);
pr.setDetectType(PR_DETECT_CMSER);
pr.setDetectType(PR_DETECT_COLOR | PR_DETECT_SOBEL);
//pr.setDetectType(PR_DETECT_CMSER);
//CPlateDetect pd;
//pd.setDetectType(PR_DETECT_CMSER);

Loading…
Cancel
Save