Skip to content

Commit aa05f7d

Browse files
committed
* change readme.
* add more data to svm. * change the svm train process, fix train data size, add new test data. * close the svm train menu.
1 parent a1045d1 commit aa05f7d

37 files changed

+107
-62524
lines changed

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ EasyPR是一个开源的中文车牌识别系统,其目标是成为一个简
6262

6363
关于本次改动的具体内容可以看博客中的[介绍](http://www.cnblogs.com/subconscious/p/5637735.html)
6464

65+
注意,目前1.4和1.5版的SVM训练好的文件在使用时会有问题,这个原因可能跟opencv3的实现改变有关。建议要训练SVM的话使用基于opencv2的1.3版。
66+
6567
### 跨平台
6668

6769
目前除了windows平台以外,还有以下其他平台的EasyPR版本。一些平台的版本可能会暂时落后于主平台。
@@ -160,6 +162,18 @@ CPlate类包含了车牌的各种信息,其中重要的如下:
160162

161163
plateMat代表车牌图像,rrect代表车牌的可旋转矩形位置,license代表车牌字符串,例如“蓝牌:苏EUK722”。
162164

165+
这里说下如何去阅读如下图的识别结果。
166+
167+
![EasyPR DetectResults](resources/doc/res/one_image_detect.jpg)
168+
169+
第1行代表的是图片的文件名。
170+
171+
第2行代表GroundTruth车牌,用后缀(g)表示。第3行代表EasyPR检测车牌,用后缀(d)表示。两者形成一个配对,第4行代表两者的字符差距。
172+
173+
下面同上。本图片中有3个车牌,所有共有三个配对。最后的Recall等指标代表的是整幅图片的定位评价,考虑了三个配对的结果。
174+
175+
有时检测车牌的部分会用“无车牌”与“No string”替代。“无车牌”代表“定位不成功”,“No string”代表“定位成功但字符分割失败”。
176+
163177
### 版权
164178

165179
EasyPR的源代码与训练数据遵循Apache v2.0协议开源。

etc/main_menu

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
EasyPR Option:
33
1. 测试;
44
2. 批量测试;
5-
3. SVM训练;
5+
3. SVM训练(暂时关闭,请用1.3版的);
66
4. ANN训练;
77
5. GDTS生成;
88
6. 开发团队;
-215 KB
Binary file not shown.
-229 KB
Binary file not shown.
-254 KB
Binary file not shown.
-173 KB
Binary file not shown.
-227 KB
Binary file not shown.
-195 KB
Binary file not shown.
-191 KB
Binary file not shown.
-232 KB
Binary file not shown.
-125 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-31.3 KB
Binary file not shown.
Binary file not shown.
-37.4 KB
Binary file not shown.
-35.4 KB
Binary file not shown.
-39.6 KB
Binary file not shown.
-35.2 KB
Binary file not shown.
-34.6 KB
Binary file not shown.
-32.6 KB
Binary file not shown.
-37.5 KB
Binary file not shown.
-38.1 KB
Binary file not shown.
-37.2 KB
Binary file not shown.
-47.5 KB
Binary file not shown.
-35.1 KB
Binary file not shown.

resources/model/svm_hisotm.xml

-23,029
This file was deleted.

resources/model/svm_lbp_final.xml

-39,452
This file was deleted.

resources/train/ann.7z

-88 KB
Binary file not shown.

resources/train/svm.7z

4.61 MB
Binary file not shown.

result/accuracy.txt

+45
Original file line numberDiff line numberDiff line change
@@ -2008,3 +2008,48 @@ Recall:84.2263%, Precise:70.6573%, Fscore:76.8474%.
20082008
Recall:84.2263%, Precise:70.6573%, Fscore:76.8474%.
20092009
0-error:60.4%, 1-error:71.6%, Chinese-precise:73.2%
20102010
��ʱ��:114��, ƽ��ִ��ʱ��:0.445313��
2011+
2016-07-05 21:37:51
2012+
��ͼƬ��:256, Plates count:297, δ��λ����:40, ��λ��:86.532%
2013+
Recall:78.8339%, Precise:53.3124%, Fscore:63.6086%.
2014+
0-error:55.3571%, 1-error:64.2857%, Chinese-precise:67.8571%
2015+
��ʱ��:114��, ƽ��ִ��ʱ��:0.445313��
2016+
2016-07-06 07:38:55
2017+
��ͼƬ��:256, Plates count:297, δ��λ����:29, ��λ��:90.2357%
2018+
Recall:84.2263%, Precise:70.6573%, Fscore:76.8474%.
2019+
0-error:60.4%, 1-error:71.6%, Chinese-precise:73.2%
2020+
��ʱ��:114��, ƽ��ִ��ʱ��:0.445313��
2021+
2016-07-06 07:46:53
2022+
��ͼƬ��:256, Plates count:297, δ��λ����:29, ��λ��:90.2357%
2023+
Recall:84.2263%, Precise:70.6573%, Fscore:76.8474%.
2024+
0-error:60.4%, 1-error:71.6%, Chinese-precise:73.2%
2025+
��ʱ��:122��, ƽ��ִ��ʱ��:0.476563��
2026+
2016-07-06 07:55:13
2027+
��ͼƬ��:3, Plates count:0, δ��λ����:0, ��λ��:-1.#IND%
2028+
Recall:0%, Precise:0%, Fscore:0%.
2029+
0-error:0%, 1-error:0%, Chinese-precise:100%
2030+
��ʱ��:3��, ƽ��ִ��ʱ��:1��
2031+
2016-07-06 07:55:42
2032+
��ͼƬ��:3, Plates count:0, δ��λ����:0, ��λ��:-1.#IND%
2033+
Recall:0%, Precise:0%, Fscore:0%.
2034+
0-error:0%, 1-error:0%, Chinese-precise:100%
2035+
��ʱ��:6��, ƽ��ִ��ʱ��:2��
2036+
2016-07-06 07:57:02
2037+
��ͼƬ��:2, Plates count:0, δ��λ����:0, ��λ��:-1.#IND%
2038+
Recall:0%, Precise:0%, Fscore:0%.
2039+
0-error:0%, 1-error:0%, Chinese-precise:100%
2040+
��ʱ��:1��, ƽ��ִ��ʱ��:0.5��
2041+
2016-07-06 07:57:45
2042+
��ͼƬ��:4, Plates count:0, δ��λ����:0, ��λ��:-1.#IND%
2043+
Recall:0%, Precise:0%, Fscore:0%.
2044+
0-error:0%, 1-error:0%, Chinese-precise:100%
2045+
��ʱ��:1��, ƽ��ִ��ʱ��:0.25��
2046+
2016-07-06 08:00:06
2047+
��ͼƬ��:256, Plates count:297, δ��λ����:29, ��λ��:90.2357%
2048+
Recall:84.2263%, Precise:70.6573%, Fscore:76.8474%.
2049+
0-error:60.4%, 1-error:71.6%, Chinese-precise:73.2%
2050+
��ʱ��:118��, ƽ��ִ��ʱ��:0.460938��
2051+
2016-07-06 08:27:36
2052+
��ͼƬ��:256, Plates count:297, δ��λ����:29, ��λ��:90.2357%
2053+
Recall:84.2263%, Precise:70.6573%, Fscore:76.8474%.
2054+
0-error:60.4%, 1-error:71.6%, Chinese-precise:73.2%
2055+
��ʱ��:123��, ƽ��ִ��ʱ��:0.480469��

src/core/plate_judge.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ namespace easypr {
3636
extractFeature(inMat, features);
3737

3838
float response = svm_->predict(features);
39+
/*std::cout << "response:" << response << std::endl;
40+
41+
float score = svm_->predict(features, noArray(), cv::ml::StatModel::Flags::RAW_OUTPUT);
42+
std::cout << "score:" << score << std::endl;*/
43+
3944
result = (int)response;
4045

4146
return 0;
@@ -64,6 +69,8 @@ namespace easypr {
6469

6570
float score = svm_->predict(features, noArray(), cv::ml::StatModel::Flags::RAW_OUTPUT);
6671

72+
//std::cout << "score:" << score << std::endl;
73+
6774
// score is the distance of margin,below zero is plate, up is not
6875
// when score is below zero, the samll the value, the more possibliy to be a plate.
6976
plate.setPlateScore(score);

src/core/plate_locate.cpp

+1-6
Original file line numberDiff line numberDiff line change
@@ -743,12 +743,6 @@ int CPlateLocate::plateColorLocate(Mat src, vector<CPlate> &candPlates,
743743
candPlates.insert(candPlates.end(), plates_blue.begin(), plates_blue.end());
744744
candPlates.insert(candPlates.end(), plates_yellow.begin(), plates_yellow.end());
745745

746-
//for (auto plate : plates_blue)
747-
// candPlates.push_back(plate);
748-
749-
//for (auto plate : plates_yellow)
750-
// candPlates.push_back(plate);
751-
752746
return 0;
753747
}
754748

@@ -1044,6 +1038,7 @@ int CPlateLocate::plateLocate(Mat src, vector<Mat> &resultVec, int index) {
10441038

10451039
plateColorLocate(src, all_result_Plates, index);
10461040
plateSobelLocate(src, all_result_Plates, index);
1041+
plateMserLocate(src, all_result_Plates, index);
10471042

10481043
for (size_t i = 0; i < all_result_Plates.size(); i++) {
10491044
CPlate plate = all_result_Plates[i];

src/train/svm_train.cpp

+27-36
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ void SvmTrain::train() {
2727
svm_->setC(1);
2828
svm_->setNu(0.1);
2929
svm_->setP(0.1);
30-
svm_->setTermCriteria(cvTermCriteria(CV_TERMCRIT_ITER, 100000, 0.00001));
30+
svm_->setTermCriteria(cvTermCriteria(CV_TERMCRIT_ITER, 20000, 0.0001));
3131

3232
auto train_data = tdata();
3333

@@ -43,6 +43,7 @@ void SvmTrain::train() {
4343
fprintf(stdout, ">> Training done. Time elapse: %ldms\n", end - start);
4444
fprintf(stdout, ">> Saving model file...\n");
4545
svm_->save(svm_xml_);
46+
4647
fprintf(stdout, ">> Your SVM Model was saved to %s\n", svm_xml_);
4748
fprintf(stdout, ">> Testing...\n");
4849
this->test();
@@ -72,11 +73,11 @@ void SvmTrain::test() {
7273
continue;
7374
}
7475
cv::Mat feature;
75-
getHistogramFeatures(image, feature);
76-
77-
//std::cout << "predict: " << result << std::endl;
76+
getLBPFeatures(image, feature);
7877

7978
auto predict = int(svm_->predict(feature));
79+
std::cout << "predict: " << predict << std::endl;
80+
8081
auto real = item.label;
8182
if (predict == kForward && real == kForward) ptrue_rtrue++;
8283
if (predict == kForward && real == kInverse) ptrue_rfalse++;
@@ -123,47 +124,37 @@ void SvmTrain::prepare() {
123124

124125
char buffer[260] = {0};
125126

126-
sprintf(buffer, "%s/has", plates_folder_);
127-
auto has_file_list = utils::getFiles(buffer);
128-
std::random_shuffle(has_file_list.begin(), has_file_list.end());
127+
sprintf(buffer, "%s/has/train", plates_folder_);
128+
auto has_file_train_list = utils::getFiles(buffer);
129+
std::random_shuffle(has_file_train_list.begin(), has_file_train_list.end());
129130

130-
sprintf(buffer, "%s/no", plates_folder_);
131-
auto no_file_list = utils::getFiles(buffer);
132-
std::random_shuffle(no_file_list.begin(), no_file_list.end());
131+
sprintf(buffer, "%s/has/test", plates_folder_);
132+
auto has_file_test_list = utils::getFiles(buffer);
133+
std::random_shuffle(has_file_test_list.begin(), has_file_test_list.end());
133134

134-
auto has_num = has_file_list.size();
135-
auto no_num = no_file_list.size();
135+
sprintf(buffer, "%s/no/train", plates_folder_);
136+
auto no_file_train_list = utils::getFiles(buffer);
137+
std::random_shuffle(no_file_train_list.begin(), no_file_train_list.end());
138+
139+
sprintf(buffer, "%s/no/test", plates_folder_);
140+
auto no_file_test_list = utils::getFiles(buffer);
141+
std::random_shuffle(no_file_test_list.begin(), no_file_test_list.end());
136142

137143
fprintf(stdout, ">> Collecting train data...\n");
138144

139-
auto has_for_train = static_cast<int>(has_num * kSvmPercentage);
140-
auto no_for_train = static_cast<int>(no_num * kSvmPercentage);
145+
for (auto file : has_file_train_list)
146+
train_file_list_.push_back({ file, kForward });
141147

142-
// copy kSvmPercentage of has_file_list to train_file_list_
143-
train_file_list_.reserve(has_for_train + no_for_train);
144-
for (auto i = 0; i < has_for_train; i++) {
145-
train_file_list_.push_back({has_file_list[i], kForward});
146-
}
147-
// copy kSvmPercentage of no_file_list to the end of train_file_list_
148-
for (auto i = 0; i < no_for_train; i++) {
149-
train_file_list_.push_back({no_file_list[i], kInverse});
150-
}
148+
for (auto file : no_file_train_list)
149+
train_file_list_.push_back({ file, kInverse });
151150

152151
fprintf(stdout, ">> Collecting test data...\n");
153152

154-
auto has_for_test = has_num - has_for_train;
155-
auto no_for_test = no_num - no_for_train;
156-
157-
// copy the rest of has_file_list to the test_file_list_
158-
test_file_list_.reserve(has_for_test + no_for_test);
159-
for (size_t i = has_for_train; i < has_num; i++) {
160-
test_file_list_.push_back({has_file_list[i], kForward});
161-
}
153+
for (auto file : has_file_test_list)
154+
test_file_list_.push_back({ file, kForward });
162155

163-
// copy the rest of no_file_list to the end of the test_file_list_
164-
for (size_t i = no_for_train; i < no_num; i++) {
165-
test_file_list_.push_back({no_file_list[i], kInverse});
166-
}
156+
for (auto file : no_file_test_list)
157+
test_file_list_.push_back({ file, kInverse });
167158
}
168159

169160
cv::Ptr<cv::ml::TrainData> SvmTrain::tdata() {
@@ -179,7 +170,7 @@ cv::Ptr<cv::ml::TrainData> SvmTrain::tdata() {
179170
continue;
180171
}
181172
cv::Mat feature;
182-
getHistogramFeatures(image, feature);
173+
getLBPFeatures(image, feature);
183174
feature = feature.reshape(1, 1);
184175

185176
samples.push_back(feature);

test/accuracy.hpp

+12
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ namespace easypr {
165165

166166
// get the ground truth and compare it with the detect list;
167167
vector<CPlate> plateVecGT;
168+
bool hasGroundTruth = true;
168169
#pragma omp critical
169170
{
170171
map<string, vector<CPlate>>::iterator it;
@@ -173,6 +174,7 @@ namespace easypr {
173174
plateVecGT = it->second;
174175
}
175176
else {
177+
hasGroundTruth = false;
176178
img_ss << "No ground truth found!" << endl;
177179
}
178180
}
@@ -268,6 +270,16 @@ namespace easypr {
268270
Rect_<float> plateRect_d;
269271
calcSafeRect(platePos_d, src, plateRect_d);
270272

273+
if (!hasGroundTruth) {
274+
string detectPlateLicense = plate_d.getPlateStr();
275+
vector<string> spilt_plate = Utils::splitString(detectPlateLicense, ':');
276+
277+
size_t size = spilt_plate.size();
278+
if (size == 2 && spilt_plate.at(1) != "") {
279+
img_ss << detectPlateLicense << " (d)" << endl;
280+
}
281+
}
282+
271283
// remain
272284
//XMLNode rectangleNode = rectangleNodes.addChild("taggedRectangle");
273285
//RotatedRect rr = platePos_d;

0 commit comments

Comments
 (0)