#include "easypr.h" #include "easypr/program_options.h" #include "accuracy.hpp" #include "chars.hpp" #include "plate.hpp" int annMain(); namespace easypr { namespace demo { // interactions int accuracyTestMain() { bool isExit = false; while (!isExit) { std::cout << "////////////////////////////////////" << std::endl; const char* options[] = {"BatchTest Option:", "1. general_test;", "2. native_test;", "3. 返回;", NULL}; Utils::print_str_lines(options); std::cout << "////////////////////////////////////" << std::endl; std::cout << "请选择一项操作:"; int select = -1; bool isRepeat = true; while (isRepeat) { std::cin >> select; isRepeat = false; switch (select) { case 1: accuracyTest("resources/image/general_test"); break; case 2: accuracyTest("resources/image/native_test"); break; case 3: isExit = true; break; default: std::cout << "输入错误,请重新输入:"; isRepeat = true; break; } } } return 0; } // int svmMain() { // bool isExit = false; // while (!isExit) { // std::cout << "////////////////////////////////////" << std::endl; // const char* options[] = { // "SvmTrain Option:", // "1. 生成learndata(调整代码到你的环境后再用);", // "2. 标签learndata;", // "3. 车牌检测(not divide and train);", // "4. 车牌检测(not train);", // "5. 车牌检测(not divide);", // "6. 车牌检测;", // "7. 返回;", // NULL // }; // Utils::print_str_lines(options); // std::cout << "////////////////////////////////////" << std::endl; // std::cout << "请选择一项操作:"; // // int select = -1; // bool isRepeat = true; // while (isRepeat) { // std::cin >> select; // isRepeat = false; // // //Svm svm; // // switch (select) { // case 1: // // easypr::preprocess::getLearnData(); // break; // case 2: // // easypr::preprocess::label_data(); // break; // case 3: // svm.train(false, false); // break; // case 4: // svm.train(true, false); // break; // case 5: // svm.train(false, true); // break; // case 6: // svm.train(); // break; // case 7: // isExit = true; // break; // default: // std::cout << "输入错误,请重新输入:"; // isRepeat = true; // break; // } // } // } // return 0; //} int testMain() { bool isExit = false; while (!isExit) { std::cout << "////////////////////////////////////" << std::endl; const char* options[] = { "EasyPR Test:", "1. test plate_locate(车牌定位);" /* 车牌定位 */, "2. test plate_judge(车牌判断);" /* 车牌判断 */, "3. test plate_detect(车牌检测);" /* 车牌检测(包含车牌定位与车牌判断) */, "4. test chars_segment(字符分隔);" /* 字符分隔 */, "5. test chars_identify(字符鉴别);" /* 字符鉴别 */, "6. test chars_recognise(字符识别);" /* 字符识别(包含字符分隔与字符鉴别) */, "7. test plate_recognize(车牌识别);" /* 车牌识别 */, "8. test all(测试全部);" /* 以上全部 */, "9. 返回;" /* 退出 */, NULL}; Utils::print_str_lines(options); std::cout << "////////////////////////////////////" << std::endl; std::cout << "请选择一项操作:"; int select = -1; bool isRepeat = true; while (isRepeat) { std::cin >> select; isRepeat = false; switch (select) { case 1: assert(test_plate_locate() == 0); break; case 2: assert(test_plate_judge() == 0); break; case 3: assert(test_plate_detect() == 0); break; case 4: assert(test_chars_segment() == 0); break; case 5: assert(test_chars_identify() == 0); break; case 6: assert(test_chars_recognise() == 0); break; case 7: assert(test_plate_recognize() == 0); break; case 8: 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_chars_recognise() == 0); assert(test_plate_recognize() == 0); break; case 9: isExit = true; break; default: std::cout << "输入错误,请重新输入:"; isRepeat = true; break; } } } return 0; } } // namespace demo } // namespace easypr void command_line_handler(int argc, const char* argv[]) { program_options::Generator options; options.add_subroutine("svm", "svm operations").make_usage("Usage:"); options("h,help", "show help information"); options(",svm", "resources/model/svm.xml", "the svm model file," " this option is used for '--tag'(required)" " and '--train'(save svm model to) functions"); // create options( ",create", "create learn data, this function " "will intercept (--max) raw images (--in) and preprocess into (--out)"); options("i,in", "", "where is the raw images"); options("o,out", "", "where to put the preprocessed images"); options("m,max", "5000", "how many learn data would you want to create"); // tag options(",tag", "tag learn data, this function " "will find plate blocks in your images(--source) " "as well as classify them into (--has) and (--no)"); options("s,source", "", "where is your images to be classified"); options(",has", "", "put plates in this folder"); options(",no", "", "put images without plate in this folder"); // train options(",train", "train given data, " "including the forward(has plate) and the inverse(no plate)."); options(",has-plate", "", "where is the forward data"); options(",no-plate", "", "where is the inverse data"); options(",divide", "whether divide train data into two parts by --percentage or not"); options(",percentage", "0.7", "70% train data will be used for training," " others will be used for testing"); options(",not-train", "don't train again, run testing directly"); options.add_subroutine("locate", "locate plates in an image") .make_usage("Usage:"); options("h,help", "show help information"); options("f,file", "", "the target picture which contains one or more plates"); options.add_subroutine( "judge", "determine whether an image block is the license plate") .make_usage("Usage:"); options("h,help", "show help information"); options("f,file", "the target image block"); options(",svm", "resources/model/svm.xml", "the svm model file"); options.add_subroutine("recognize", "plate recognition").make_usage("Usage:"); options("h,help", "show help information"); options("p,path", "", "where is the target picture or target folder"); options("b,batch", "do batch recognition, if set, --path means a folder"); options("c,color", "returns the plate color, blue or yellow"); options(",svm", "resources/model/svm.xml", "the svm model file"); options(",ann", "resources/model/ann.xml", "the ann model file"); auto parser = options.make_parser(); try { parser->parse(argc, argv); } catch (const std::exception& err) { std::cout << err.what() << std::endl; return; } auto subname = parser->get_subroutine_name(); if (subname == "svm") { if (parser->has("help") || argc <= 2) { std::cout << options("svm"); return; } if (parser->has("create")) { assert(parser->has("in")); assert(parser->has("out")); assert(parser->has("max")); auto in = parser->get("in")->val(); auto out = parser->get("out")->val(); auto max = parser->get("max")->as(); easypr::preprocess::create_learn_data(in.c_str(), out.c_str(), max); } if (parser->has("tag")) { assert(parser->has("source")); assert(parser->has("has")); assert(parser->has("no")); assert(parser->has("svm")); auto source = parser->get("source")->val(); auto has_path = parser->get("has")->val(); auto no_path = parser->get("no")->val(); auto svm = parser->get("svm")->val(); easypr::preprocess::tag_data(source.c_str(), has_path.c_str(), no_path.c_str(), svm.c_str()); std::cout << "Tagging finished, check out output images " << "and classify the wrong images manually." << std::endl; } if (parser->has("train")) { assert(parser->has("has-plate")); assert(parser->has("no-plate")); assert(parser->has("percentage")); assert(parser->has("svm")); auto forward_data_path = parser->get("has-plate")->val(); auto inverse_data_path = parser->get("no-plate")->val(); bool divide = parser->has("divide"); auto percentage = parser->get("percentage")->as(); auto svm_model = parser->get("svm")->val(); bool not_train = parser->has("not-train"); easypr::Svm svm(forward_data_path.c_str(), inverse_data_path.c_str()); svm.train(divide, percentage, !not_train, svm_model.c_str()); } return; } else if (subname == "locate") { if (parser->has("help") || argc <= 2) { std::cout << options("locate"); return; } if (parser->has("file")) { easypr::api::plate_locate(parser->get("file")->val().c_str()); std::cout << "finished, results can be found in tmp/" << std::endl; } return; } else if (subname == "judge") { if (parser->has("help") || argc <= 2) { std::cout << options("judge"); std::cout << "Note that the input image's size should " << "be the same as the one you gived to svm train." << std::endl; return; } if (parser->has("file")) { assert(parser->has("file")); assert(parser->has("svm")); auto image = parser->get("file")->val(); auto svm = parser->get("svm")->val(); const char* true_or_false[2] = {"false", "true"}; std::cout << true_or_false[easypr::api::plate_judge(image.c_str(), svm.c_str())] << std::endl; } return; } else if (subname == "recognize") { if (parser->has("help") || argc <= 2) { std::cout << options("recognize"); return; } if (parser->has("path")) { if (parser->has("batch")) { // batch testing auto folder = parser->get("path")->val(); easypr::demo::accuracyTest(folder.c_str()); } else { // single testing auto image = parser->get("path")->val(); if (parser->has("color")) { // return plate color const char* colors[2] = {"blue", "yellow"}; std::cout << colors[easypr::api::get_plate_color(image.c_str())] << std::endl; } else { // return strings auto svm = parser->get("svm")->val(); auto ann = parser->get("ann")->val(); auto results = easypr::api::plate_recognize(image.c_str(), svm.c_str(), ann.c_str()); for (auto s : results) { std::cout << s << std::endl; } } } } else { std::cout << "option 'file' cannot be empty." << std::endl; } return; } // no case matched, print all commands. std::cout << "There are several sub commands listed below, " << "choose one by typing:\n\n" << " " << easypr::Utils::getFileName(argv[0]) << " command [options]\n\n" << "The commands are:\n" << std::endl; auto subs = options.get_subroutine_list(); for (auto sub : subs) { fprintf(stdout, "%s %s\n", sub.first.c_str(), sub.second.c_str()); } std::cout << std::endl; } int main(int argc, const char* argv[]) { if (argc > 1) { // handle command line execution. command_line_handler(argc, argv); return 0; } bool isExit = false; while (!isExit) { std::cout << "////////////////////////////////////" << std::endl; const char* options[] = {"EasyPR Option:", "1. 测试;", "2. 批量测试;", "3. SVM训练;", "4. ANN训练;", "5. GDTS生成;", "6. 开发团队;", "7. 感谢名单;", "8. 退出;", NULL}; easypr::Utils::print_str_lines(options); std::cout << "////////////////////////////////////" << std::endl; std::cout << "请选择一项操作:"; int select = -1; bool isRepeat = true; while (isRepeat) { std::cin >> select; isRepeat = false; switch (select) { case 1: easypr::demo::testMain(); break; case 2: easypr::demo::accuracyTestMain(); break; case 3: // easypr::demo::svmMain(); std::cout << "Run \"easypr_test svm\" for more usage." << std::endl; { easypr::Svm svm("resources/train/data/plate_detect_svm/learn/HasPlate", "resources/train/data/plate_detect_svm/learn/NoPlate"); svm.train(); } break; case 4: // TODO { annMain(); } break; case 5: easypr::preprocess::generate_gdts(); break; case 6: { // 开发团队; std::cout << std::endl; const char* recruitment[] = { "我们EasyPR团队目前有一个5人左右的小组在进行EasyPR后续版本的开发" "工作。", "如果你对本项目感兴趣,并且愿意为开源贡献一份力量,我们很欢迎你的" "加入。", "目前招聘的主要人才是:车牌定位,图像识别,深度学习,网站建设相关" "方面的牛人。", "如果你觉得自己符合条件,请发邮件到地址(easypr_dev@163.com)" ",期待你的加入!", NULL}; easypr::Utils::print_str_lines(recruitment); std::cout << std::endl; break; } case 7: { // 感谢名单 std::cout << std::endl; const char* thanks[] = { "本项目在建设过程中,受到了很多人的帮助,其中以下是对本项目做出突" "出贡献的", "(贡献包括有益建议,代码调优,数据提供等等,排名按时间顺序):", "taotao1233,邱锦山,唐大侠,jsxyhelu,如果有一天(zhoushiwei),", "学习奋斗,袁承志,圣城小石匠,goldriver,Micooz,梦里时光,", "Rain Wang,ahccoms,星夜落尘,海豚嘎嘎", "还有很多的同学对本项目也给予了鼓励与支持,在此也一并表示真诚的谢" "意!", NULL}; easypr::Utils::print_str_lines(thanks); std::cout << std::endl; break; } case 8: isExit = true; break; default: std::cout << "输入错误,请重新输入:"; isRepeat = true; break; } } } return 0; }