* add new chinese gray images for trainging (about 600)

* general test change to utf-8
v1.6alpha
liuruoze 8 years ago
parent 029e014a51
commit 1e604768db

@ -84,6 +84,12 @@ static const int kCharsTotalNumber = 65;
static bool kDebug = false; static bool kDebug = false;
// Disable the copy and assignment operator for this class.
#define DISABLE_ASSIGN_AND_COPY(className) \
private:\
className& operator=(const className&); \
className(const className&)
} }
#endif // EASYPR_CONFIG_H_ #endif // EASYPR_CONFIG_H_

@ -11,9 +11,12 @@ namespace easypr {
class CCharsSegment { class CCharsSegment {
public: public:
CCharsSegment(); CCharsSegment();
//! using ostu algotithm the segment chars in plate
int charsSegment(Mat input, std::vector<Mat>& resultVec, Color color = BLUE); int charsSegment(Mat input, std::vector<Mat>& resultVec, Color color = BLUE);
//! using project the segment chars in plate
int charsSegmentUsingProject(Mat input, std::vector<Mat>& resultVec, std::vector<Mat>& grayChars, Color color = BLUE);
bool verifyCharSizes(Mat r); bool verifyCharSizes(Mat r);
// find the best chinese binaranzation method // find the best chinese binaranzation method
@ -30,7 +33,6 @@ class CCharsSegment {
//! Do two things //! Do two things
// 1.remove rect in the left of city character // 1.remove rect in the left of city character
// 2.from the city rect, to the right, choose 6 rects // 2.from the city rect, to the right, choose 6 rects
int RebuildRect(const std::vector<Rect>& vecRect, std::vector<Rect>& outRect, int RebuildRect(const std::vector<Rect>& vecRect, std::vector<Rect>& outRect,
int specIndex); int specIndex);

@ -6,6 +6,7 @@
#include "easypr/core/character.hpp" #include "easypr/core/character.hpp"
using namespace cv; using namespace cv;
using namespace std;
/*! \namespace easypr /*! \namespace easypr
Namespace where all the C++ EasyPR functionality resides Namespace where all the C++ EasyPR functionality resides
@ -40,8 +41,10 @@ Rect GetCenterRect(Mat& in);
Mat CutTheRect(Mat& in, Rect& rect); Mat CutTheRect(Mat& in, Rect& rect);
int ThresholdOtsu(Mat mat); int ThresholdOtsu(Mat mat);
// project histogram
Mat ProjectedHistogram(Mat img, int t, int threshold = 20);
Mat ProjectedHistogram(Mat img, int t); Mat showHistogram(const Mat& hist);
Mat preprocessChar(Mat in, int char_size); Mat preprocessChar(Mat in, int char_size);
@ -106,13 +109,19 @@ Mat translateImg(Mat img, int offsetx, int offsety);
Mat rotateImg(Mat source, float angle); Mat rotateImg(Mat source, float angle);
// uniform resize all the image to same size for the next process // uniform resize all the image to same size for the next process
Mat uniformResize(const Mat &result); Mat uniformResize(const Mat &result, float& scale);
// show detect results // show detect results
void showDectectResults(const Mat& img, const std::vector<CPlate> &plateVec, size_t num); void showDectectResults(const Mat& img, const std::vector<CPlate> &plateVec, size_t num);
// show the results // show the results
Mat showResult(const Mat &result, int img_index = 0); Mat showResult(const Mat &result, int img_index = 0);
// enlarge the char rect
Rect rectEnlarge(const Rect& src, const int mat_width, const int mat_height);
// write images to temp folder
void writeTempImage(const Mat& outImg, const string path);
} /*! \namespace easypr*/ } /*! \namespace easypr*/
#endif // EASYPR_CORE_COREFUNC_H_ #endif // EASYPR_CORE_COREFUNC_H_

@ -6,34 +6,34 @@
namespace easypr { namespace easypr {
//! 获得车牌的特征数 //! 获得车牌的特征数
cv::Mat getHistogram(cv::Mat in); cv::Mat getHistogram(cv::Mat in);
//! EasyPR的getFeatures回调函数 //! EasyPR的getFeatures回调函数
//! 用于从车牌的image生成svm的训练特征features //! 用于从车牌的image生成svm的训练特征features
typedef void (*svmCallback)(const cv::Mat& image, cv::Mat& features); typedef void (*svmCallback)(const cv::Mat& image, cv::Mat& features);
//! EasyPR的getFeatures回调函数 //! EasyPR的getFeatures回调函数
//! 本函数是获取垂直和水平的直方图图值 //! 本函数是获取垂直和水平的直方图图值
void getHistogramFeatures(const cv::Mat& image, cv::Mat& features); void getHistogramFeatures(const cv::Mat& image, cv::Mat& features);
//! 本函数是获取SIFT特征子 //! 本函数是获取SIFT特征子
void getSIFTFeatures(const cv::Mat& image, cv::Mat& features); void getSIFTFeatures(const cv::Mat& image, cv::Mat& features);
//! 本函数是获取HOG特征子 //! 本函数是获取HOG特征子
void getHOGFeatures(const cv::Mat& image, cv::Mat& features); void getHOGFeatures(const cv::Mat& image, cv::Mat& features);
//! 本函数是获取HSV空间量化的直方图特征子 //! 本函数是获取HSV空间量化的直方图特征子
void getHSVHistFeatures(const cv::Mat& image, cv::Mat& features); void getHSVHistFeatures(const cv::Mat& image, cv::Mat& features);
//! LBP feature //! LBP feature
void getLBPFeatures(const cv::Mat& image, cv::Mat& features); void getLBPFeatures(const cv::Mat& image, cv::Mat& features);
//! color feature
void getColorFeatures(const cv::Mat& src, cv::Mat& features);
//! color feature and histom
void getHistomPlusColoFeatures(const cv::Mat& image, cv::Mat& features);
//! get character feature //! get character feature
cv::Mat charFeatures(cv::Mat in, int sizeData); cv::Mat charFeatures(cv::Mat in, int sizeData);
cv::Mat charFeatures2(cv::Mat in, int sizeData); cv::Mat charFeatures2(cv::Mat in, int sizeData);

@ -88,6 +88,9 @@ namespace easypr {
inline void setPlateColor(Color param) { m_plateColor = param; } inline void setPlateColor(Color param) { m_plateColor = param; }
inline Color getPlateColor() const { return m_plateColor; } inline Color getPlateColor() const { return m_plateColor; }
inline void setPlateScale(float param) { m_scale = param; }
inline float getPlateScale() const { return m_scale; }
inline void setPlateScore(double param) { m_score = param; } inline void setPlateScore(double param) { m_score = param; }
inline double getPlateScore() const { return m_score; } inline double getPlateScore() const { return m_score; }
@ -139,6 +142,9 @@ namespace easypr {
//! plate color type //! plate color type
Color m_plateColor; Color m_plateColor;
//! scale ratio
float m_scale;
//! plate likely //! plate likely
double m_score; double m_score;

@ -42,6 +42,7 @@ namespace easypr {
private: private:
// show the detect and recognition result image // show the detect and recognition result image
bool m_showResult; bool m_showResult;
DISABLE_ASSIGN_AND_COPY(CPlateRecognize);
}; };
} /* \namespace easypr */ } /* \namespace easypr */

@ -4,6 +4,7 @@
#include "easypr/train/train.h" #include "easypr/train/train.h"
#include <vector> #include <vector>
#include "easypr/config.h" #include "easypr/config.h"
#include "easypr/core/feature.h"
namespace easypr { namespace easypr {
@ -32,6 +33,8 @@ class SvmTrain : public ITrain {
const char* svm_xml_; const char* svm_xml_;
std::vector<TrainItem> train_file_list_; std::vector<TrainItem> train_file_list_;
std::vector<TrainItem> test_file_list_; std::vector<TrainItem> test_file_list_;
svmCallback extractFeature;
}; };
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,6 +1,7 @@
#include "easypr/core/chars_recognise.h" #include "easypr/core/chars_recognise.h"
#include "easypr/core/character.hpp" #include "easypr/core/character.hpp"
#include "easypr/util/util.h" #include "easypr/util/util.h"
#include <ctime>
namespace easypr { namespace easypr {
@ -47,11 +48,15 @@ int CCharsRecognise::charsRecognise(Mat plate, std::string& plateLicense) {
return result; return result;
} }
int char_index = 0;
int plate_index = 0;
int CCharsRecognise::charsRecognise(CPlate& plate, std::string& plateLicense) { int CCharsRecognise::charsRecognise(CPlate& plate, std::string& plateLicense) {
std::vector<Mat> matChars; std::vector<Mat> matChars;
std::vector<Mat> grayChars;
Mat plateMat = plate.getPlateMat(); Mat plateMat = plate.getPlateMat();
if (1) {
writeTempImage(plateMat, "plateMat/plate");
}
Color color; Color color;
if (plate.getPlateLocateType() == CMSER) { if (plate.getPlateLocateType() == CMSER) {
color = plate.getPlateColor(); color = plate.getPlateColor();
@ -63,22 +68,17 @@ int CCharsRecognise::charsRecognise(CPlate& plate, std::string& plateLicense) {
color = getPlateType(tmpMat, true); color = getPlateType(tmpMat, true);
} }
int result = m_charsSegment->charsSegment(plateMat, matChars, color); int result = m_charsSegment->charsSegmentUsingProject(plateMat, matChars, grayChars,color);
//std::cout << "charsSegment:" << result << std::endl; //std::cout << "charsSegment:" << result << std::endl;
if (result == 0) { if (result == 0) {
//for (auto block : matChars) {
// auto character = CharsIdentify::instance()->identify(block);
// plateLicense.append(character.second);
//}
int num = matChars.size(); int num = matChars.size();
for (int j = 0; j < num; j++) for (int j = 0; j < num; j++)
{ {
Mat charMat = matChars.at(j); Mat charMat = matChars.at(j);
Mat grayChar = grayChars.at(j);
bool isChinses = false; bool isChinses = false;
//if (j == 0)
// isChinses = true;
//auto character = CharsIdentify::instance()->identify(charMat, isChinses);
//plateLicense.append(character.second);
std::pair<std::string, std::string> character; std::pair<std::string, std::string> character;
float maxVal; float maxVal;
if (j == 0) { if (j == 0) {
@ -86,6 +86,18 @@ int CCharsRecognise::charsRecognise(CPlate& plate, std::string& plateLicense) {
bool judge = true; bool judge = true;
character = CharsIdentify::instance()->identifyChinese(charMat, maxVal, judge); character = CharsIdentify::instance()->identifyChinese(charMat, maxVal, judge);
plateLicense.append(character.second); plateLicense.append(character.second);
//time_t t = time(0); // get time now
//struct tm* now = localtime(&t);
//char buf[80];
//strftime(buf, sizeof(buf), "%Y-%m-%d %H_%M_%S", now);
//if (1) {
// std::stringstream ss(std::stringstream::in | std::stringstream::out);
// ss << "resources/image/tmp/grayChars/" << character.first << "/chars_" << char_index++ << "_" << std::string(buf) << ".jpg";
// imwrite(ss.str(), grayChar);
//}
if (1) {
writeTempImage(grayChar, "grayChars/" + character.first + "/chars_");
}
} }
else { else {
isChinses = false; isChinses = false;

@ -242,40 +242,6 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec, Color color)
Mat img_threshold; Mat img_threshold;
//if (BLUE == plateType) {
// // cout << "BLUE" << endl;
// img_threshold = input_grey.clone();
// int w = input_grey.cols;
// int h = input_grey.rows;
// Mat tmp = input_grey(Rect_<double>(w * 0.1, h * 0.1, w * 0.8, h * 0.8));
// int threadHoldV = ThresholdOtsu(tmp);
// threshold(input_grey, img_threshold, threadHoldV, 255, CV_THRESH_BINARY);
//} else if (YELLOW == plateType) {
// // cout << "YELLOW" << endl;
// img_threshold = input_grey.clone();
// int w = input_grey.cols;
// int h = input_grey.rows;
// Mat tmp = input_grey(Rect_<double>(w * 0.1, h * 0.1, w * 0.8, h * 0.8));
// int threadHoldV = ThresholdOtsu(tmp);
// // utils::imwrite("resources/image/tmp/inputgray2.jpg", input_grey);
// threshold(input_grey, img_threshold, threadHoldV, 255,
// CV_THRESH_BINARY_INV);
//} else if (WHITE == plateType) {
// // cout << "WHITE" << endl;
// threshold(input_grey, img_threshold, 10, 255,
// CV_THRESH_OTSU + CV_THRESH_BINARY_INV);
//} else {
// // cout << "UNKNOWN" << endl;
// threshold(input_grey, img_threshold, 10, 255,
// CV_THRESH_OTSU + CV_THRESH_BINARY);
//}
img_threshold = input_grey.clone(); img_threshold = input_grey.clone();
spatial_ostu(img_threshold, 8, 2, plateType); spatial_ostu(img_threshold, 8, 2, plateType);
@ -287,10 +253,7 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec, Color color)
// remove liuding and hor lines // remove liuding and hor lines
// also judge weather is plate use jump count // also judge weather is plate use jump count
if (!clearLiuDing(img_threshold)) return 0x02; if (!clearLiuDing(img_threshold)) return 0x02;
//clearLiuDing(img_threshold);
Mat img_contours; Mat img_contours;
img_threshold.copyTo(img_contours); img_threshold.copyTo(img_contours);
@ -399,6 +362,158 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec, Color color)
return 0; return 0;
} }
int index_1 = 0;
int CCharsSegment::charsSegmentUsingProject(Mat input, vector<Mat>& resultVec, vector<Mat>& grayChars, Color color) {
if (!input.data) return 0x01;
Color plateType = color;
Mat input_grey;
cvtColor(input, input_grey, CV_BGR2GRAY);
if (0) {
imshow("plate", input_grey);
waitKey(0);
destroyWindow("plate");
}
if (1) {
std::stringstream ss(std::stringstream::in | std::stringstream::out);
ss << "resources/image/tmp/plateMatGray/plate_" << index_1++ << ".jpg";
imwrite(ss.str(), input_grey);
}
Mat img_threshold;
img_threshold = input_grey.clone();
spatial_ostu(img_threshold, 8, 2, plateType);
if (0) {
imshow("plate", img_threshold);
waitKey(0);
destroyWindow("plate");
}
// remove liuding and hor lines
// also judge weather is plate use jump count
if (!clearLiuDing(img_threshold)) return 0x02;
//Mat vhist = ProjectedHistogram(img_threshold, VERTICAL, 0);
//Mat showHist = showHistogram(vhist);
//if (0) {
// imshow("showHist", showHist);
// waitKey(0);
// destroyWindow("showHist");
//}
Mat img_contours;
img_threshold.copyTo(img_contours);
vector<vector<Point> > contours;
findContours(img_contours,
contours, // a vector of contours
CV_RETR_EXTERNAL, // retrieve the external contours
CV_CHAIN_APPROX_NONE); // all pixels of each contours
vector<vector<Point> >::iterator itc = contours.begin();
vector<Rect> vecRect;
while (itc != contours.end()) {
Rect mr = boundingRect(Mat(*itc));
Mat auxRoi(img_threshold, mr);
if (verifyCharSizes(auxRoi)) vecRect.push_back(mr);
++itc;
}
if (vecRect.size() == 0) return 0x03;
vector<Rect> sortedRect(vecRect);
std::sort(sortedRect.begin(), sortedRect.end(),
[](const Rect& r1, const Rect& r2) { return r1.x < r2.x; });
size_t specIndex = 0;
specIndex = GetSpecificRect(sortedRect);
Rect chineseRect;
if (specIndex < sortedRect.size())
chineseRect = GetChineseRect(sortedRect[specIndex]);
else
return 0x04;
if (0) {
rectangle(img_threshold, chineseRect, Scalar(255));
imshow("plate", img_threshold);
waitKey(0);
destroyWindow("plate");
}
vector<Rect> newSortedRect;
newSortedRect.push_back(chineseRect);
RebuildRect(sortedRect, newSortedRect, specIndex);
if (newSortedRect.size() == 0) return 0x05;
bool useSlideWindow = true;
bool useAdapThreshold = true;
//bool useAdapThreshold = CParams::instance()->getParam1b();
for (size_t i = 0; i < newSortedRect.size(); i++) {
Rect mr = newSortedRect[i];
Rect large_mr = rectEnlarge(mr, input_grey.cols, input_grey.rows);
Mat grayChar(input_grey, large_mr);
Mat auxRoi(input_grey, mr);
Mat newRoi;
if (i == 0) {
if (useSlideWindow) {
float slideLengthRatio = 0.1f;
//float slideLengthRatio = CParams::instance()->getParam1f();
if (!slideChineseWindow(input_grey, mr, newRoi, plateType, slideLengthRatio, useAdapThreshold))
judgeChinese(auxRoi, newRoi, plateType);
}
else
judgeChinese(auxRoi, newRoi, plateType);
}
else {
if (BLUE == plateType) {
threshold(auxRoi, newRoi, 0, 255, CV_THRESH_BINARY + CV_THRESH_OTSU);
}
else if (YELLOW == plateType) {
threshold(auxRoi, newRoi, 0, 255, CV_THRESH_BINARY_INV + CV_THRESH_OTSU);
}
else if (WHITE == plateType) {
threshold(auxRoi, newRoi, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV);
}
else {
threshold(auxRoi, newRoi, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);
}
newRoi = preprocessChar(newRoi);
}
if (0) {
if (i == 0) {
imshow("input_grey", input_grey);
waitKey(0);
destroyWindow("input_grey");
}
if (i == 0) {
imshow("newRoi", newRoi);
waitKey(0);
destroyWindow("newRoi");
}
}
grayChars.push_back(grayChar);
resultVec.push_back(newRoi);
}
return 0;
}
Rect CCharsSegment::GetChineseRect(const Rect rectSpe) { Rect CCharsSegment::GetChineseRect(const Rect rectSpe) {
int height = rectSpe.height; int height = rectSpe.height;

@ -4,18 +4,14 @@
#include "easypr/config.h" #include "easypr/config.h"
#include "easypr/core/params.h" #include "easypr/core/params.h"
#include "thirdparty/mser/mser2.hpp" #include "thirdparty/mser/mser2.hpp"
#include <ctime>
using namespace cv;
namespace easypr { namespace easypr {
Mat colorMatch(const Mat &src, Mat &match, const Color r, Mat colorMatch(const Mat &src, Mat &match, const Color r,
const bool adaptive_minsv) { const bool adaptive_minsv) {
// if use adaptive_minsv // if use adaptive_minsv
// min value of s and v is adaptive to h // min value of s and v is adaptive to h
const float max_sv = 255; const float max_sv = 255;
const float minref_sv = 64; const float minref_sv = 64;
@ -644,14 +640,14 @@ float countOfBigValue(Mat &mat, int iValue) {
} }
} }
Mat ProjectedHistogram(Mat img, int t) { Mat ProjectedHistogram(Mat img, int t, int threshold) {
int sz = (t) ? img.rows : img.cols; int sz = (t) ? img.rows : img.cols;
Mat mhist = Mat::zeros(1, sz, CV_32F); Mat mhist = Mat::zeros(1, sz, CV_32F);
for (int j = 0; j < sz; j++) { for (int j = 0; j < sz; j++) {
Mat data = (t) ? img.row(j) : img.col(j); Mat data = (t) ? img.row(j) : img.col(j);
mhist.at<float>(j) = countOfBigValue(data, 20); mhist.at<float>(j) = countOfBigValue(data, threshold);
} }
// Normalize histogram // Normalize histogram
@ -664,6 +660,22 @@ Mat ProjectedHistogram(Mat img, int t) {
return mhist; return mhist;
} }
Mat showHistogram(const Mat& hist) {
int height = 32;
int width = hist.cols;
Mat show = Mat::zeros(height, width, CV_8UC1);
for (int i = 0; i < width; i++) {
int len = int((float)height * hist.at<float>(i));
for (int j = height-1; j >= 0; j--) {
if (height - j <= len)
show.at<char>(j, i) = (char)255;
}
}
return show;
}
Mat preprocessChar(Mat in, int char_size) { Mat preprocessChar(Mat in, int char_size) {
// Remap image // Remap image
int h = in.rows; int h = in.rows;
@ -2291,7 +2303,7 @@ bool calcSafeRect(const RotatedRect &roi_rect, const int width, const int height
} }
Mat uniformResize(const Mat &result) { Mat uniformResize(const Mat &result, float& scale) {
const int RESULTWIDTH = kShowWindowWidth; // 640 930 const int RESULTWIDTH = kShowWindowWidth; // 640 930
const int RESULTHEIGHT = kShowWindowHeight; // 540 710 const int RESULTHEIGHT = kShowWindowHeight; // 540 710
@ -2304,25 +2316,24 @@ Mat uniformResize(const Mat &result) {
Mat result_resize; Mat result_resize;
if (nCols <= img_window.cols && nRows <= img_window.rows) { if (nCols <= img_window.cols && nRows <= img_window.rows) {
result_resize = result; result_resize = result;
} }
else if (nCols > img_window.cols && nRows <= img_window.rows) { else if (nCols > img_window.cols && nRows <= img_window.rows) {
float scale = float(img_window.cols) / float(nCols); scale = float(img_window.cols) / float(nCols);
resize(result, result_resize, Size(), scale, scale, CV_INTER_AREA); resize(result, result_resize, Size(), scale, scale, CV_INTER_AREA);
} }
else if (nCols <= img_window.cols && nRows > img_window.rows) { else if (nCols <= img_window.cols && nRows > img_window.rows) {
float scale = float(img_window.rows) / float(nRows); scale = float(img_window.rows) / float(nRows);
resize(result, result_resize, Size(), scale, scale, CV_INTER_AREA); resize(result, result_resize, Size(), scale, scale, CV_INTER_AREA);
} }
else if (nCols > img_window.cols && nRows > img_window.rows) { else if (nCols > img_window.cols && nRows > img_window.rows) {
Mat result_middle; Mat result_middle;
float scale = float(img_window.cols) / float(nCols); scale = float(img_window.cols) / float(nCols);
resize(result, result_middle, Size(), scale, scale, CV_INTER_AREA); resize(result, result_middle, Size(), scale, scale, CV_INTER_AREA);
if (result_middle.rows > img_window.rows) { if (result_middle.rows > img_window.rows) {
float scale = float(img_window.rows) / float(result_middle.rows); scale = float(img_window.rows) / float(result_middle.rows);
resize(result_middle, result_resize, Size(), scale, scale, CV_INTER_AREA); resize(result_middle, result_resize, Size(), scale, scale, CV_INTER_AREA);
} }
else { else {
@ -2332,7 +2343,6 @@ Mat uniformResize(const Mat &result) {
else { else {
result_resize = result; result_resize = result;
} }
return result_resize; return result_resize;
} }
@ -2434,4 +2444,52 @@ Mat showResult(const Mat &result, int img_index) {
return img_window; return img_window;
} }
Rect rectEnlarge(const Rect& src,const int mat_width, const int mat_height) {
float w = (float)src.width;
float h = (float)src.height;
// enlarge the rect,
// width to 120%
// height to 105%
float new_w = w * 1.2f;
float new_h = h * 1.05f;
Rect_<float> boudRect;
boudRect.x = (float)src.x - w * 0.1f;
boudRect.y = (float)src.y - h * 0.025f;
boudRect.width = new_w;
boudRect.height = new_h;
float tl_x = boudRect.x > 0 ? boudRect.x : 0;
float tl_y = boudRect.y > 0 ? boudRect.y : 0;
float br_x = boudRect.x + boudRect.width < mat_width
? boudRect.x + boudRect.width - 1
: mat_width - 1;
float br_y = boudRect.y + boudRect.height < mat_height
? boudRect.y + boudRect.height - 1
: mat_height - 1;
float roi_width = br_x - tl_x;
float roi_height = br_y - tl_y;
Rect dst(0,0,0,0);
if (roi_width <= 0 || roi_height <= 0)
return dst;
//! a new rect not out the range of mat
dst = Rect_<float>(tl_x, tl_y, roi_width, roi_height);
return dst;
}
void writeTempImage(const Mat& outImg, const string path) {
std::stringstream ss(std::stringstream::in | std::stringstream::out);
time_t t = time(0); // get time now
struct tm* now = localtime(&t);
char buf[80];
strftime(buf, sizeof(buf), "%Y-%m-%d %H_%M_%S", now);
ss << "resources/image/tmp/" << path << "_" << std::string(buf) << ".jpg";
imwrite(ss.str(), outImg);
}
} }

@ -38,14 +38,70 @@ void getHistogramFeatures(const Mat& image, Mat& features) {
//grayImage = histeq(grayImage); //grayImage = histeq(grayImage);
Mat img_threshold; Mat img_threshold;
threshold(grayImage, img_threshold, 0, 255, threshold(grayImage, img_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);
CV_THRESH_OTSU + CV_THRESH_BINARY); //Mat img_threshold = grayImage.clone();
//spatial_ostu(img_threshold, 8, 2, getPlateType(image, false));
features = getHistogram(img_threshold); features = getHistogram(img_threshold);
} }
// compute color histom
void getColorFeatures(const Mat& src, Mat& features) {
Mat src_hsv;
void getSIFTFeatures(const Mat& image, Mat& features) { //grayImage = histeq(grayImage);
cvtColor(src, src_hsv, CV_BGR2HSV);
int channels = src_hsv.channels();
int nRows = src_hsv.rows;
// consider multi channel image
int nCols = src_hsv.cols * channels;
if (src_hsv.isContinuous()) {
nCols *= nRows;
nRows = 1;
}
const int sz = 180;
int h[sz] = { 0 };
uchar* p;
for (int i = 0; i < nRows; ++i) {
p = src_hsv.ptr<uchar>(i);
for (int j = 0; j < nCols; j += 3) {
int H = int(p[j]); // 0-180
if (H > sz - 1) H = sz - 1;
if (H < 0) H = 0;
h[H]++;
}
}
Mat mhist = Mat::zeros(1, sz, CV_32F);
for (int j = 0; j < sz; j++) {
mhist.at<float>(j) = (float)h[j];
}
// Normalize histogram
double min, max;
minMaxLoc(mhist, &min, &max);
if (max > 0)
mhist.convertTo(mhist, -1, 1.0f / max, 0);
features = mhist;
}
void getHistomPlusColoFeatures(const Mat& image, Mat& features) {
// TODO
Mat feature1, feature2;
getHistogramFeatures(image, feature1);
getColorFeatures(image, feature2);
hconcat(feature1.reshape(1, 1), feature2.reshape(1, 1), features);
}
void getSIFTFeatures(const Mat& image, Mat& features) {
// TODO
} }
@ -60,10 +116,10 @@ void getHOGFeatures(const Mat& image, Mat& features) {
Mat trainImg = Mat(dsize, CV_32S); Mat trainImg = Mat(dsize, CV_32S);
resize(image, trainImg, dsize); resize(image, trainImg, dsize);
//compute descripter // compute descripter
hog->compute(trainImg, descriptor, Size(8, 8)); hog->compute(trainImg, descriptor, Size(8, 8));
//copy the result // copy the result
Mat mat_featrue(descriptor); Mat mat_featrue(descriptor);
mat_featrue.copyTo(features); mat_featrue.copyTo(features);
} }

@ -22,7 +22,7 @@ namespace easypr {
} }
else { else {
svm_ = ml::SVM::load<ml::SVM>(kHistSvmPath); svm_ = ml::SVM::load<ml::SVM>(kHistSvmPath);
extractFeature = getHistogramFeatures; extractFeature = getHistomPlusColoFeatures;
} }
} }

@ -466,8 +466,6 @@ int CPlateLocate::deskew(const Mat &src, const Mat &src_b,
destroyWindow("bound_mat_b"); destroyWindow("bound_mat_b");
} }
//std::cout << "roi_angle:" << roi_angle << std::endl;
Point2f roi_ref_center = roi_rect.center - safeBoundRect.tl(); Point2f roi_ref_center = roi_rect.center - safeBoundRect.tl();
Mat deskew_mat; Mat deskew_mat;
@ -475,21 +473,16 @@ int CPlateLocate::deskew(const Mat &src, const Mat &src_b,
-90.0 == roi_angle) { -90.0 == roi_angle) {
deskew_mat = bound_mat; deskew_mat = bound_mat;
} else { } else {
Mat rotated_mat; Mat rotated_mat;
Mat rotated_mat_b; Mat rotated_mat_b;
if (!rotation(bound_mat, rotated_mat, roi_rect_size, roi_ref_center, if (!rotation(bound_mat, rotated_mat, roi_rect_size, roi_ref_center, roi_angle))
roi_angle))
continue; continue;
if (!rotation(bound_mat_b, rotated_mat_b, roi_rect_size, roi_ref_center, if (!rotation(bound_mat_b, rotated_mat_b, roi_rect_size, roi_ref_center, roi_angle))
roi_angle))
continue; continue;
// we need affine for rotatioed image // we need affine for rotatioed image
double roi_slope = 0; double roi_slope = 0;
// imshow("1roated_mat",rotated_mat); // imshow("1roated_mat",rotated_mat);
// imshow("rotated_mat_b",rotated_mat_b); // imshow("rotated_mat_b",rotated_mat_b);
@ -499,7 +492,6 @@ int CPlateLocate::deskew(const Mat &src, const Mat &src_b,
deskew_mat = rotated_mat; deskew_mat = rotated_mat;
} }
Mat plate_mat; Mat plate_mat;
plate_mat.create(HEIGHT, WIDTH, TYPE); plate_mat.create(HEIGHT, WIDTH, TYPE);
@ -507,10 +499,7 @@ int CPlateLocate::deskew(const Mat &src, const Mat &src_b,
if (useDeteleArea) if (useDeteleArea)
deleteNotArea(deskew_mat, color); deleteNotArea(deskew_mat, color);
if (deskew_mat.cols * 1.0 / deskew_mat.rows > 2.3 && deskew_mat.cols * 1.0 / deskew_mat.rows < 6) {
if (deskew_mat.cols * 1.0 / deskew_mat.rows > 2.3 &&
deskew_mat.cols * 1.0 / deskew_mat.rows < 6) {
if (deskew_mat.cols >= WIDTH || deskew_mat.rows >= HEIGHT) if (deskew_mat.cols >= WIDTH || deskew_mat.rows >= HEIGHT)
resize(deskew_mat, plate_mat, plate_mat.size(), 0, 0, INTER_AREA); resize(deskew_mat, plate_mat, plate_mat.size(), 0, 0, INTER_AREA);
else else
@ -520,12 +509,10 @@ int CPlateLocate::deskew(const Mat &src, const Mat &src_b,
plate.setPlatePos(roi_rect); plate.setPlatePos(roi_rect);
plate.setPlateMat(plate_mat); plate.setPlateMat(plate_mat);
if (color != UNKNOWN) plate.setPlateColor(color); if (color != UNKNOWN) plate.setPlateColor(color);
outPlates.push_back(plate); outPlates.push_back(plate);
} }
} }
} }
return 0; return 0;
} }
@ -764,14 +751,6 @@ int CPlateLocate::plateMserLocate(Mat src, vector<CPlate> &candPlates, int img_i
Mat grayImage; Mat grayImage;
cvtColor(src, grayImage, COLOR_BGR2GRAY); cvtColor(src, grayImage, COLOR_BGR2GRAY);
channelImages.push_back(grayImage); channelImages.push_back(grayImage);
//Mat singleChannelImage;
//extractChannel(src, singleChannelImage, 2);
//channelImages.push_back(singleChannelImage);
//flags.push_back(BLUE);
//channelImages.push_back(255 - grayImage);
//flags.push_back(YELLOW);
} }
for (size_t i = 0; i < channelImages.size(); ++i) { for (size_t i = 0; i < channelImages.size(); ++i) {
@ -806,14 +785,11 @@ int CPlateLocate::plateMserLocate(Mat src, vector<CPlate> &candPlates, int img_i
rects_mser.push_back(scaleRect); rects_mser.push_back(scaleRect);
mserPlate.push_back(plate); mserPlate.push_back(plate);
//all_plates.push_back(plate);
} }
Mat resize_src_b; Mat resize_src_b;
resize(src_b, resize_src_b, Size(channelImage.cols, channelImage.rows)); resize(src_b, resize_src_b, Size(channelImage.cols, channelImage.rows));
//src_b_vec.push_back(resize_src_b);
deskew(src, resize_src_b, rects_mser, deskewPlate, false, color); deskew(src, resize_src_b, rects_mser, deskewPlate, false, color);
for (auto dplate : deskewPlate) { for (auto dplate : deskewPlate) {
@ -832,46 +808,8 @@ int CPlateLocate::plateMserLocate(Mat src, vector<CPlate> &candPlates, int img_i
} }
} }
} }
} }
//if (usePlateMser) {
// std::vector<RotatedRect> plateRRect_B;
// std::vector<RotatedRect> plateRRect_Y;
// for (auto rrect : all_plateRRect) {
// RotatedRect theRect = scaleBackRRect(rrect, (float)scale_ratio);
// //rotatedRectangle(src, theRect, Scalar(255, 0, 0));
// for (auto plate : all_plates) {
// RotatedRect plateRect = plate.getPlatePos();
// //rotatedRectangle(src, plateRect, Scalar(0, 255, 0));
// bool isSimilar = computeIOU(theRect, plateRect, src, 0.8f);
// if (isSimilar) {
// //rotatedRectangle(src, theRect, Scalar(0, 0, 255));
// Color color = plate.getPlateColor();
// if (color == BLUE) plateRRect_B.push_back(theRect);
// if (color == YELLOW) plateRRect_Y.push_back(theRect);
// }
// }
// }
// for (size_t i = 0; i < channelImages.size(); ++i) {
// Color color = flags.at(i);
// Mat resize_src_b = src_b_vec.at(i);
// std::vector<CPlate> deskewMserPlate;
// if (color == BLUE)
// deskew(src, resize_src_b, plateRRect_B, deskewMserPlate, false, color);
// if (color == YELLOW)
// deskew(src, resize_src_b, plateRRect_Y, deskewMserPlate, false, color);
// for (auto plate : deskewMserPlate) {
// candPlates.push_back(plate);
// }
// }
//}
if (0) { if (0) {
imshow("src", src); imshow("src", src);
waitKey(0); waitKey(0);

@ -15,7 +15,8 @@ CPlateRecognize::CPlateRecognize() {
int CPlateRecognize::plateRecognize(const Mat& src, std::vector<CPlate> &plateVecOut, int img_index) { int CPlateRecognize::plateRecognize(const Mat& src, std::vector<CPlate> &plateVecOut, int img_index) {
// resize to uniform sizes // resize to uniform sizes
// TODO: groungTruth affect // TODO: groungTruth affect
Mat img = uniformResize(src); float scale = 1.f;
Mat img = uniformResize(src, scale);
if (0) { if (0) {
std::stringstream ss(std::stringstream::in | std::stringstream::out); std::stringstream ss(std::stringstream::in | std::stringstream::out);
@ -37,6 +38,11 @@ int CPlateRecognize::plateRecognize(const Mat& src, std::vector<CPlate> &plateVe
destroyWindow("plate"); destroyWindow("plate");
} }
// scale the rect to src;
item.setPlateScale(scale);
RotatedRect rect = item.getPlatePos();
item.setPlatePos(scaleBackRRect(rect, 1.f / scale));
// get plate color // get plate color
Color color = item.getPlateColor(); Color color = item.getPlateColor();
if (color == UNKNOWN) { if (color == UNKNOWN) {
@ -57,17 +63,17 @@ int CPlateRecognize::plateRecognize(const Mat& src, std::vector<CPlate> &plateVe
plateVecOut.push_back(item); plateVecOut.push_back(item);
} }
else { else {
std::string license = plateColor; /*std::string license = plateColor;
item.setPlateStr(license); item.setPlateStr(license);
plateVecOut.push_back(item); plateVecOut.push_back(item);
if (0) { if (0) {
std::cout << "resultCR:" << resultCR << std::endl; std::cout << "resultCR:" << resultCR << std::endl;
} }*/
} }
} }
if (getResultShow()) { if (getResultShow()) {
// param type: 0 detect, 1 recognize; // param type: 0 detect, 1 recognize;
int showType = 0; int showType = 1;
if (0 == showType) if (0 == showType)
showDectectResults(img, plateVec, num); showDectectResults(img, plateVec, num);
else else

@ -1,5 +1,4 @@
#include "easypr/train/svm_train.h" #include "easypr/train/svm_train.h"
#include "easypr/core/feature.h"
#include "easypr/util/util.h" #include "easypr/util/util.h"
#ifdef OS_WINDOWS #ifdef OS_WINDOWS
@ -14,6 +13,8 @@ SvmTrain::SvmTrain(const char* plates_folder, const char* xml)
: plates_folder_(plates_folder), svm_xml_(xml) { : plates_folder_(plates_folder), svm_xml_(xml) {
assert(plates_folder); assert(plates_folder);
assert(xml); assert(xml);
extractFeature = getHistomPlusColoFeatures;
} }
void SvmTrain::train() { void SvmTrain::train() {
@ -33,10 +34,10 @@ void SvmTrain::train() {
fprintf(stdout, ">> Training SVM model, please wait...\n"); fprintf(stdout, ">> Training SVM model, please wait...\n");
long start = utils::getTimestamp(); long start = utils::getTimestamp();
//svm_->trainAuto(train_data, 10, SVM::getDefaultGrid(SVM::C), /*svm_->trainAuto(train_data, 10, SVM::getDefaultGrid(SVM::C),
// SVM::getDefaultGrid(SVM::GAMMA), SVM::getDefaultGrid(SVM::P), SVM::getDefaultGrid(SVM::GAMMA), SVM::getDefaultGrid(SVM::P),
// SVM::getDefaultGrid(SVM::NU), SVM::getDefaultGrid(SVM::COEF), SVM::getDefaultGrid(SVM::NU), SVM::getDefaultGrid(SVM::COEF),
// SVM::getDefaultGrid(SVM::DEGREE), true); SVM::getDefaultGrid(SVM::DEGREE), true);*/
svm_->train(train_data); svm_->train(train_data);
long end = utils::getTimestamp(); long end = utils::getTimestamp();
@ -74,7 +75,7 @@ void SvmTrain::test() {
continue; continue;
} }
cv::Mat feature; cv::Mat feature;
getLBPFeatures(image, feature); extractFeature(image, feature);
auto predict = int(svm_->predict(feature)); auto predict = int(svm_->predict(feature));
//std::cout << "predict: " << predict << std::endl; //std::cout << "predict: " << predict << std::endl;
@ -171,7 +172,7 @@ cv::Ptr<cv::ml::TrainData> SvmTrain::tdata() {
continue; continue;
} }
cv::Mat feature; cv::Mat feature;
getLBPFeatures(image, feature); extractFeature(image, feature);
feature = feature.reshape(1, 1); feature = feature.reshape(1, 1);
samples.push_back(feature); samples.push_back(feature);

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

Loading…
Cancel
Save