|
|
// 数据预处理的程序,主要做以下两件事
|
|
|
// 1.读取原生数据 rawdata,这可能有数百万张
|
|
|
// 2.随机/选择性地选取部分数据成为learndata,这个根据参数设置,一般设置为1000,10000,或者1百万
|
|
|
|
|
|
#include "easypr/preprocess/mc_data.h"
|
|
|
#include <ctime>
|
|
|
#include "easypr/core/plate_judge.h"
|
|
|
#include "easypr/core/plate_locate.h"
|
|
|
#include "easypr/util/util.h"
|
|
|
|
|
|
#ifdef OS_WINDOWS
|
|
|
#include <io.h>
|
|
|
#endif
|
|
|
|
|
|
namespace easypr {
|
|
|
|
|
|
namespace preprocess {
|
|
|
|
|
|
// std::map<std::string, std::string> mc_map = {
|
|
|
// {"E00", "未识别"},
|
|
|
// {"A01", "京"},
|
|
|
// {"A02", "津"},
|
|
|
// {"A03", "沪"},
|
|
|
// {"A04", "渝"},
|
|
|
// {"B01", "桂"},
|
|
|
// {"B02", "蒙"},
|
|
|
// {"B03", "宁"},
|
|
|
// {"B04", "新"},
|
|
|
// {"B05", "藏"},
|
|
|
// {"S01", "皖"},
|
|
|
// {"S02", "闽"},
|
|
|
// {"S03", "粤"},
|
|
|
// {"S04", "甘"},
|
|
|
// {"S05", "贵"},
|
|
|
// {"S06", "鄂"},
|
|
|
// {"S07", "冀"},
|
|
|
// {"S08", "黑"},
|
|
|
// {"S09", "湘"},
|
|
|
// {"S10", "豫"},
|
|
|
// {"S11", "琼"},
|
|
|
// {"S12", "吉"},
|
|
|
// {"S13", "苏"},
|
|
|
// {"S14", "赣"},
|
|
|
// {"S15", "辽"},
|
|
|
// {"S16", "青"},
|
|
|
// {"S17", "川"},
|
|
|
// {"S18", "鲁"},
|
|
|
// {"S19", "陕"},
|
|
|
// {"S20", "晋"},
|
|
|
// {"S21", "云"},
|
|
|
// {"S22", "浙"},
|
|
|
// {"J01", "军"},
|
|
|
// {"J02", "海"},
|
|
|
// {"J03", "空"},
|
|
|
// {"J04", "北"},
|
|
|
// {"J05", "成"},
|
|
|
// {"J06", "广"},
|
|
|
// {"J07", "济"},
|
|
|
// {"J08", "兰"},
|
|
|
// {"J09", "南"},
|
|
|
// {"J10", "沈"}
|
|
|
//};
|
|
|
|
|
|
// 切去上部与底部干扰的细节
|
|
|
|
|
|
cv::Mat cut_top_bottom(const cv::Mat& img) {
|
|
|
int width = img.size().width;
|
|
|
int height = img.size().height;
|
|
|
// TODO: it seems not correctly.
|
|
|
cv::Rect rect(0, 0, width, int(height * 0.97));
|
|
|
return img(rect);
|
|
|
}
|
|
|
|
|
|
// std::string code_to_province(const std::string& code) {
|
|
|
// return (mc_map.find(code) != mc_map.end()) ? mc_map[code] : "无";
|
|
|
//}
|
|
|
|
|
|
//// 通过filepath获取车牌号码
|
|
|
//// 文件名格式:A01_00000
|
|
|
// std::string plate_from_path(const std::string& path) {
|
|
|
// auto filename = Utils::getFileName(path);
|
|
|
// auto code = filename.substr(0, 3);
|
|
|
// return code_to_province(code) + filename.substr(3);
|
|
|
//}
|
|
|
|
|
|
// 将rawdata截取部分数据到learndata中
|
|
|
|
|
|
void create_learn_data(const char* raw_data_folder, const char* out_data_folder,
|
|
|
const int how_many /* = 5000 */) {
|
|
|
assert(raw_data_folder);
|
|
|
assert(out_data_folder);
|
|
|
|
|
|
auto files = Utils::getFiles(raw_data_folder);
|
|
|
|
|
|
size_t size = files.size();
|
|
|
if (0 == size) {
|
|
|
std::cout << "No file found in " << raw_data_folder << std::endl;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 随机排列rawdata
|
|
|
|
|
|
srand(unsigned(time(NULL)));
|
|
|
std::random_shuffle(files.begin(), files.end());
|
|
|
|
|
|
int count = 0;
|
|
|
for (auto f : files) {
|
|
|
|
|
|
// 选取前how_many个rawdata数据作为learndata
|
|
|
|
|
|
if (count++ >= how_many) {
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
//读取数据,并对图片进行预处理
|
|
|
|
|
|
cv::Mat img = cv::imread(f);
|
|
|
img = cut_top_bottom(img);
|
|
|
|
|
|
std::string save_to(out_data_folder);
|
|
|
if (*(save_to.end() - 1) != '/') {
|
|
|
save_to.push_back('/');
|
|
|
}
|
|
|
save_to.append(Utils::getFileName(f, true));
|
|
|
|
|
|
utils::imwrite(save_to, img);
|
|
|
std::cout << f << " -> " << save_to << std::endl;
|
|
|
}
|
|
|
std::cout << "Learn data created successfully!" << std::endl;
|
|
|
}
|
|
|
|
|
|
// 定位并判断车牌有无,放置在指定位置
|
|
|
|
|
|
void tag_data(const char* source_folder, const char* has_plate_folder,
|
|
|
const char* no_plate_folder, const char* svm_model) {
|
|
|
assert(source_folder);
|
|
|
assert(has_plate_folder);
|
|
|
assert(no_plate_folder);
|
|
|
assert(svm_model);
|
|
|
|
|
|
auto files = Utils::getFiles(source_folder);
|
|
|
|
|
|
size_t size = files.size();
|
|
|
if (0 == size) {
|
|
|
std::cout << "No file found in " << source_folder << std::endl;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
CPlateLocate locator;
|
|
|
|
|
|
for (auto f : files) {
|
|
|
auto filename = Utils::getFileName(f);
|
|
|
std::cout << "Tagging: " << f << std::endl;
|
|
|
|
|
|
// auto plate_string = plate_from_path(f);
|
|
|
cv::Mat image = cv::imread(f);
|
|
|
assert(!image.empty());
|
|
|
|
|
|
std::vector<cv::Mat> maybe_plates;
|
|
|
locator.plateLocate(image, maybe_plates);
|
|
|
|
|
|
int plate_index = 0;
|
|
|
for (auto plate : maybe_plates) {
|
|
|
char save_to[255] = {0};
|
|
|
int result = 0;
|
|
|
PlateJudge::instance()->plateJudge(plate, result);
|
|
|
if (result == 1) {
|
|
|
// it's a plate
|
|
|
sprintf(save_to, "%s/%s_%d.jpg", has_plate_folder, filename.c_str(),
|
|
|
plate_index);
|
|
|
std::cout << "[Y] -> " << save_to << std::endl;
|
|
|
} else {
|
|
|
// no plate found
|
|
|
sprintf(save_to, "%s/%s_%d.jpg", no_plate_folder, filename.c_str(),
|
|
|
plate_index);
|
|
|
std::cout << "[N] -> " << save_to << std::endl;
|
|
|
}
|
|
|
utils::imwrite(save_to, plate);
|
|
|
++plate_index;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} // namespace preprocess
|
|
|
|
|
|
} // namespace easypr
|