Structural optimization.

Command Line Shell enhancement.
Support compiling to static library(libeasypr).
Provide frequently used apis(api.hpp) for quick access to functions what users want.
SVM train without changing source files.
Fix OpenCV roi out of range bug.
The language layer fix and optimization, type matching, loop simplified using C++11.
1.3
Micooz 10 years ago
parent 4a379d265c
commit c888179d81

@ -1,15 +1,15 @@
cmake_minimum_required(VERSION 2.8)
project (easypr)
project (EasyPR)
# c++11 required
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
# opencv package required
find_package(OpenCV REQUIRED)
set(CMAKE_SOURCE_DIR ./src)
# easypr library
include_directories(include)
set(SOURCE_FILES
src/main.cpp
src/core/core_func.cpp
src/core/chars_identify.cpp
src/core/chars_recognise.cpp
@ -20,18 +20,18 @@ set(SOURCE_FILES
src/core/plate_judge.cpp
src/core/plate_locate.cpp
src/core/plate_recognize.cpp
src/test/accuracy_test.cpp
src/test/test.cpp
src/train/ann_train.cpp
src/train/svm_train.cpp
src/util/deface.cpp
src/util/general_test_prepare.cpp
src/util/generate_gdts.cpp
src/util/learn_prepare.cpp
src/util/mc_data_prepare.cpp
src/preprocess/deface.cpp
src/preprocess/general_test_prepare.cpp
src/preprocess/gdts.cpp
src/preprocess/mc_data.cpp
src/util/util.cpp
src/util/CParser.cpp
src/util/program_options.cpp
)
add_library(easypr STATIC ${SOURCE_FILES})
# test cases
add_executable(easypr_test test/main.cpp)
add_executable(EasyPR ${SOURCE_FILES})
target_link_libraries(EasyPR ${OpenCV_LIBS})
target_link_libraries(easypr_test ${OpenCV_LIBS} easypr)

@ -83,7 +83,7 @@ EasyPR不需要安装开发者直接在其上做改动。如果想使用DLL
|目录 | 解释
|------|----------
| general_test | GDTS通用数据测试集
| natvie_test | NDTS本地数据测试集
| native_test | NDTS本地数据测试集
| tmp | Debug模式下EasyPR输出中间图片的目录
以下表格是src目录中子目录的解释:
@ -122,7 +122,7 @@ EasyPR不需要安装开发者直接在其上做改动。如果想使用DLL
| svm_train.cpp | svm训练函数
| generate_gdts.cpp | GDTS生成函数
### Contributer
### Contributors
* liuruoze1.0-1.2版核心代码作者
@ -138,9 +138,6 @@ EasyPR不需要安装开发者直接在其上做改动。如果想使用DLL
### 鸣谢
taotao1233邱锦山唐大侠jsxyhelu如果有一天(zhoushiwei)学习奋斗袁承志圣城小石匠goldriverMicooz梦里时光Rain Wang任薛纪ahccom星夜落尘海豚嘎嘎
taotao1233邱锦山唐大侠jsxyhelu如果有一天(zhoushiwei),学习奋斗,袁承志,
圣城小石匠goldriverMicooz梦里时光Rain Wang任薛纪ahccom星夜落尘海豚嘎嘎

File diff suppressed because it is too large Load Diff

@ -0,0 +1,12 @@
#ifndef EASYPR_EASYPR_H
#define EASYPR_EASYPR_H
#include "easypr/plate_recognize.h"
#include "easypr/svm_train.h"
#include "easypr/preprocess/mc_data.h"
#include "easypr/preprocess/gdts.h"
#include "easypr/preprocess/deface.h"
#include "easypr/util.h"
#include "easypr/api.hpp"
#endif //EASYPR_EASYPR_H

@ -0,0 +1,79 @@
/*
* This file provides some of the most commonly used application interfaces.
*/
#ifndef EASYPR_API_HPP
#define EASYPR_API_HPP
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
namespace easypr {
namespace api {
const char* kDefaultSVMModel = "resources/model/svm.xml";
const char* kDefaultANNModel = "resourecs/model/ann.xml";
static bool plate_judge(const char* image,const char *model) {
Mat src = imread(image);
assert(!src.empty());
CPlateJudge judger;
judger.LoadModel(model);
int result;
judger.plateJudge(src, result);
return result == 1;
}
static void plate_locate(const char* image, const bool life_mode = true) {
Mat src = imread(image);
assert(!src.empty());
CPlateLocate plate;
plate.setDebug(1);
plate.setLifemode(life_mode);
std::vector<cv::Mat> results;
plate.plateLocate(src, results);
}
static std::vector<std::string> plate_recognize(const char* image,
const char* model_svm,
const char* model_ann,
const bool life_mode = true) {
cv::Mat img = cv::imread(image);
assert(!img.empty());
CPlateRecognize pr;
pr.LoadSVM(model_svm);
pr.LoadANN(model_ann);
pr.setLifemode(life_mode);
pr.setDebug(false);
std::vector<std::string> results;
pr.plateRecognize(img, results);
return std::move(results);
}
static Color get_plate_color(const char* image) {
cv::Mat img = cv::imread(image);
assert(!img.empty());
return getPlateType(img, true);
}
}
}
#endif //EASYPR_API_HPP

@ -7,28 +7,28 @@
namespace easypr {
//! 获得车牌的特征数
Mat getTheFeatures(Mat in);
cv::Mat getTheFeatures(cv::Mat in);
//! EasyPR的getFeatures回调函数
//! 用于从车牌的image生成svm的训练特征features
typedef void(*svmCallback)(const Mat& image, Mat& features);
typedef void(*svmCallback)(const cv::Mat& image, cv::Mat& features);
//! EasyPR的getFeatures回调函数
//! 本函数是生成直方图均衡特征的回调函数
void getHisteqFeatures(const Mat& image, Mat& features);
void getHisteqFeatures(const cv::Mat& image, cv::Mat& features);
//! EasyPR的getFeatures回调函数
//! 本函数是获取垂直和水平的直方图图值
void getHistogramFeatures(const Mat& image, Mat& features);
void getHistogramFeatures(const cv::Mat& image, cv::Mat& features);
//! 本函数是获取SIFT特征子
void getSIFTFeatures(const Mat& image, Mat& features);
void getSIFTFeatures(const cv::Mat& image, cv::Mat& features);
//! 本函数是获取HOG特征子
void getHOGFeatures(const Mat& image, Mat& features);
void getHOGFeatures(const cv::Mat& image, cv::Mat& features);
//! 本函数是获取HSV空间量化的直方图特征子
void getHSVHistFeatures(const Mat& image, Mat& features);
void getHSVHistFeatures(const cv::Mat& image, cv::Mat& features);
} /*! \namespace easypr*/

@ -0,0 +1,57 @@
//////////////////////////////////////////////////////////////////////////
// Name: plate_judge Header
// Version: 1.1
// Date: 2014-09-28
// MDate: 2015-01-28
// Author: liuruoze
// Copyright: liuruoze
// Reference: Mastering OpenCV with Practical Computer Vision Projects
// Reference: CSDN Bloger taotao1233
// Desciption:
// Defines CPlateLocate
//////////////////////////////////////////////////////////////////////////
#ifndef __PLATE_JUDGE_H__
#define __PLATE_JUDGE_H__
#include "prep.h"
#include "plate.h"
#include "feature.h"
#include "core_func.h"
/*! \namespace easypr
Namespace where all the C++ EasyPR functionality resides
*/
namespace easypr {
class CPlateJudge {
public:
CPlateJudge();
//! 对多幅车牌进行SVM判断
int plateJudge(const vector<CPlate>&, vector<CPlate>&);
//! 车牌判断
int plateJudge(const vector<Mat>&, vector<Mat>&);
//! 车牌判断(一副图像)
int plateJudge(const Mat& inMat, int& result);
//! 直方图均衡
Mat histeq(Mat);
//! 装载SVM模型
void LoadModel(const char* model);
private:
//使用的SVM模型
CvSVM svm;
// ! EasyPR的getFeatures回调函数
// 用于从车牌的image生成svm的训练特征features
svmCallback m_getFeatures;
};
} /*! \namespace easypr*/
#endif /* endif __PLATE_JUDGE_H__ */

@ -0,0 +1,47 @@
//////////////////////////////////////////////////////////////////////////
// Name: plate_recognize Header
// Version: 1.0
// Date: 2014-09-28
// Author: liuruoze
// Copyright: liuruoze
// Reference: Mastering OpenCV with Practical Computer Vision Projects
// Reference: CSDN Bloger taotao1233
// Desciption:
// Defines CPlateRecognize
//////////////////////////////////////////////////////////////////////////
#ifndef __PLATE_RECOGNIZE_H__
#define __PLATE_RECOGNIZE_H__
#include "prep.h"
#include "plate_detect.h"
#include "chars_recognise.h"
/*! \namespace easypr
Namespace where all the C++ EasyPR functionality resides
*/
namespace easypr {
class CPlateRecognize : public CPlateDetect, public CCharsRecognise {
public:
CPlateRecognize();
//! 车牌检测与字符识别
int plateRecognize(Mat src, vector<string>& licenseVec);
//! 生活模式与工业模式切换
inline void setLifemode(bool param) {
CPlateDetect::setPDLifemode(param);
}
//! 是否开启调试模式
inline void setDebug(int param) {
CPlateDetect::setPDDebug(param);
CCharsRecognise::setCRDebug(param);
}
};
} /* \namespace easypr */
#endif /* endif __PLATE_RECOGNITION_H__ */

@ -0,0 +1,29 @@
// 人脸马赛克
//
// Created by zhou shiwei on 15/1/20.
// Copyright (c) 2015年 zhou shiwei. All rights reserved.
// 反人脸识别文件
// 在发布数据到general_test数据集里请先用这里的方法对图像进行处理
// EasyPR开源项目非常注重保护图片中驾驶人的隐私
#ifndef EASYPR_DEFACE_H
#define EASYPR_DEFACE_H
#include <opencv2/opencv.hpp>
namespace easypr {
namespace preprocess {
int deface();
cv::Mat detectAndMaskFace(cv::Mat& img, cv::CascadeClassifier& cascade,
double scale);
}
}
#endif //EASYPR_DEFACE_H

@ -0,0 +1,23 @@
// 生成GDTS的文件
// 在捐赠数据到GDTS数据集里请先用这里的方法对图像进行预处理
// EasyPR开源项目非常注重保护原始图片的版权
// 所有的捐赠数据通过GDSL协议进行约定保证使用人仅用于非商业性目的
#ifndef EASYPR_GDTS_H
#define EASYPR_GDTS_H
#include <opencv2/opencv.hpp>
namespace easypr {
namespace preprocess {
// EasyPR的图像预处理函数进行模糊化与裁剪化处理
cv::Mat imageProcess(cv::Mat src);
int generate_gdts();
}
}
#endif //EASYPR_GDTS_H

@ -0,0 +1,32 @@
// learn data_prepare :
// 生成learn data的cpplearn data指的是train dataverify data test data的总和这个名字是我起的。
// learn data应该是贴好标签的数据因此即便通过EasyPR自动化处理以后也要人为的修正一下.
// 你应该按照如下的步骤和顺序组织learn data
// 1.用EasyPR对not label data进行处理通过EasyPR辅助来对车牌图片进行标签放到不同文件夹下
// 2.标签分两种,一种是有车牌的,一种是无车牌的;
// 2.EasyPR生成标签以后你还得需要肉眼确认下将被不正确标签的数据转移到它们该去的文件夹下
// 3.通过上面的步骤正确的车牌图片和非车牌图片已经被分别放到两个文件下假设是hasplate和noplate
// 4.将这两个文件夹放到EasyPR目录train/data/plate_detect_svm/learn下面
// 5.运行EasyPR选择“训练”目录下的“车牌检测not divide这个程序会自动把learn data分块训练测试
#ifndef EASYPR_MC_DATA_H
#define EASYPR_MC_DATA_H
#include <string>
namespace easypr {
namespace preprocess {
void create_learn_data(const char* raw_data_folder, const char* out_data_folder,
const int how_many = 5000);
void tag_data(const char* source_folder, const char* has_plate_folder,
const char* no_plate_folder, const char* svm_model);
}
}
#endif //EASYPR_MC_DATA_H

File diff suppressed because it is too large Load Diff

@ -0,0 +1,46 @@
//
// Created by Micooz on 15/5/21.
//
#ifndef EASYPR_SVM_TRAIN_H
#define EASYPR_SVM_TRAIN_H
#include <vector>
#include <opencv2/opencv.hpp>
#include "easypr/feature.h"
namespace easypr {
class Svm {
public:
int train(bool dividePrepared = true, bool trainPrepared = true,
svmCallback getFeatures = getHistogramFeatures);
void accuracy(cv::Mat& testingclasses_preditc, cv::Mat& testingclasses_real);
void getNoPlateTest(std::vector<cv::Mat>& testingImages,
std::vector<int>& testingLabels);
void getHasPlateTest(std::vector<cv::Mat>& testingImages,
std::vector<int>& testingLabels);
void getNoPlateTrain(cv::Mat& trainingImages,
std::vector<int>& trainingLabels,
svmCallback getFeatures = getHisteqFeatures);
void getHasPlateTrain(cv::Mat& trainingImages,
std::vector<int>& trainingLabels,
svmCallback getFeatures = getHisteqFeatures);
void learn2NoPlate(float bound = 0.7);
void learn2HasPlate(float bound = 0.7);
};
}
#endif //EASYPR_SVM_TRAIN_H

@ -0,0 +1,100 @@
#ifndef EASYPR_UTIL_H_
#define EASYPR_UTIL_H_
#include <iostream>
#include <string>
#include <vector>
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
namespace easypr {
class Utils {
public:
static long getTimestamp();
/*
* Get file name from a given path
* bool postfix: including the postfix
*/
static std::string getFileName(const std::string& path,
const bool postfix = false);
/*
* Split the given string into segements by a delimiter
*/
static std::vector<std::string> splitString(const std::string& str,
const char delimiter);
/*
* returns the smaller of the two numbers
*/
template<typename T>
static T min(const T& v1, const T& v2) {
return (v1 < v2) ? v1 : v2;
}
/*
* Get files from a given folder
* all: including all sub-folders
*/
static std::vector<std::string> getFiles(const std::string& folder,
const bool all = true);
/*
* Print string lines to std::out from an array of const char*,
* this function is used for displaying command tips.
* lines: should be end with (const char*)NULL.
*/
static void print_str_lines(const char** lines) {
int index = 0;
while (lines[index++]) {
std::cout << lines[index - 1] << std::endl;
}
}
/*
* Print string lines using {"string1", "string2"},
* this is a easier way benefit from C++11.
*/
static void print_str_lines(const std::initializer_list<const char*>& lines) {
for (auto line : lines) {
std::cout << line << std::endl;
}
}
//! levenshtein距离用于计算两个车牌的距离
//EasyPR中用levenshtein距离衡量车牌识别与真实车牌的误差
template<class T>
static unsigned int levenshtein_distance(const T& s1, const T& s2) {
const size_t len1 = s1.size(), len2 = s2.size();
std::vector<unsigned int> col(len2 + 1), prevCol(len2 + 1);
for (unsigned int i = 0; i < prevCol.size(); i++)
prevCol[i] = i;
for (unsigned int i = 0; i < len1; i++) {
col[0] = i + 1;
for (unsigned int j = 0; j < len2; j++)
col[j + 1] = easypr::Utils::min(
easypr::Utils::min(prevCol[1 + j] + 1, col[j] + 1), \
prevCol[j] + (s1[i] == s2[j] ? 0 : 1));
col.swap(prevCol);
}
return prevCol[len2];
}
};
} // namespace easypr
/// general_test_prepare.cpp中方法
int general_test();
#endif // EASYPR_UTIL_H_

@ -38,7 +38,7 @@ EasyPR版本更新
![fetures](res/fetures.png)
* 新增Debug模式。可以在image/tmp文件夹下看到所有输出的中间图片。
* 新增Debug模式。可以在tmp文件夹下看到所有输出的中间图片。
![Debug模式](res/debug.jpg)

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save