add slide windows and mser- method

v1.6alpha
liuruoze 10 years ago
parent ad45ffac85
commit cf33fca08b

@ -1593,3 +1593,27 @@
总图片数:200, 未识出图片:7, 定位率:96.5%
平均字符差距:0.689119, 完全匹配数:132, 完全匹配率:68.3938%
总时间:178秒, 平均执行时间:0.89秒
2016-06-17 12:59:08
总图片数:50, 未识出图片:27, 定位率:46%
平均字符差距:2.43478, 完全匹配数:6, 完全匹配率:26.087%
总时间:587秒, 平均执行时间:11.74秒
2016-06-17 14:17:02
总图片数:50, 未识出图片:50, 定位率:0%
平均字符差距:0, 完全匹配数:0, 完全匹配率:0%
总时间:342秒, 平均执行时间:6.84秒
2016-06-17 14:35:54
总图片数:50, 未识出图片:50, 定位率:0%
平均字符差距:0, 完全匹配数:0, 完全匹配率:0%
总时间:424秒, 平均执行时间:8.48秒
2016-06-17 14:41:32
总图片数:50, 未识出图片:50, 定位率:0%
平均字符差距:0, 完全匹配数:0, 完全匹配率:0%
总时间:234秒, 平均执行时间:4.68秒
2016-06-17 15:00:50
总图片数:50, 未识出图片:50, 定位率:0%
平均字符差距:0, 完全匹配数:0, 完全匹配率:0%
总时间:331秒, 平均执行时间:6.62秒
2016-06-17 15:16:31
总图片数:200, 未识出图片:7, 定位率:96.5%
平均字符差距:0.689119, 完全匹配数:132, 完全匹配率:68.3938%
总时间:289秒, 平均执行时间:1.445秒

@ -54,21 +54,20 @@ namespace easypr {
private:
//! character mat
Mat m_characterMat;
//! character rect
Rect m_characterPos;
//! character str
String m_characterStr;
//! character likely
double m_score;
//! weather is chinese
bool isChinese;
};
} /*! \namespace easypr*/

@ -57,7 +57,7 @@ Color getPlateType(const Mat& src, const bool adaptive_minsv);
//! 直方图均衡
Mat histeq(Mat in);
Mat features(Mat in, int sizeData);
Mat charFeatures(Mat in, int sizeData);
Rect GetCenterRect(Mat& in);
Mat CutTheRect(Mat& in, Rect& rect);
int ThresholdOtsu(Mat mat);

@ -7,7 +7,7 @@ namespace easypr {
//! 获得车牌的特征数
cv::Mat getTheFeatures(cv::Mat in);
cv::Mat getHistogram(cv::Mat in);
//! EasyPR的getFeatures回调函数
//! 用于从车牌的image生成svm的训练特征features

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 270 KiB

@ -778,7 +778,7 @@ namespace cv
// dont need when plate is blue
preprocess1(src, level_size);
if (!params.pass2Only)
//pass(src, msers, bboxes, size, level_size, 0);
pass(src, msers, bboxes, size, level_size, 0);
// brighter to darker (MSER-)
preprocess2(src, level_size);

@ -1,4 +1,5 @@
#include "easypr/core/chars_identify.h"
#include "easypr/core/character.hpp"
#include "easypr/config.h"
#include "easypr/core/core_func.h"
@ -96,7 +97,7 @@ namespace easypr {
}
bool CharsIdentify::isCharacter(cv::Mat input, std::string& label, float& maxVal, bool isChinese) {
cv::Mat feature = features(input, kPredictSize);
cv::Mat feature = charFeatures(input, kPredictSize);
auto index = static_cast<int>(classify(feature, maxVal, isChinese));
if (isChinese)
@ -118,8 +119,32 @@ namespace easypr {
return false;
}
/*bool CharsIdentify::charsJudge(std::vector<CCharacter>& charVec) {
cv::Mat feature = charFeatures(input, kPredictSize);
auto index = static_cast<int>(classify(feature, maxVal, isChinese));
if (isChinese)
std::cout << "maxVal:" << maxVal << std::endl;
if (maxVal >= 0.9) {
if (index < kCharactersNumber) {
label = std::make_pair(kChars[index], kChars[index]).second;
}
else {
const char* key = kChars[index];
std::string s = key;
std::string province = kv_->get(s);
label = std::make_pair(s, province).second;
}
return true;
}
else
return false;
}*/
std::pair<std::string, std::string> CharsIdentify::identify(cv::Mat input, bool isChinese) {
cv::Mat feature = features(input, kPredictSize);
cv::Mat feature = charFeatures(input, kPredictSize);
float maxVal = -2;
auto index = static_cast<int>(classify(feature, maxVal, isChinese));
if (index < kCharactersNumber) {
@ -139,7 +164,7 @@ namespace easypr {
size_t input_size = inputs.size();
for (size_t i = 0; i < input_size; i++) {
Mat input = inputs[i];
cv::Mat feature = features(input, kPredictSize);
cv::Mat feature = charFeatures(input, kPredictSize);
featureRows.push_back(feature);
}

@ -685,7 +685,7 @@ Rect GetCenterRect(Mat &in) {
return _rect;
}
Mat features(Mat in, int sizeData) {
Mat charFeatures(Mat in, int sizeData) {
//抠取中间区域
@ -720,8 +720,7 @@ Mat features(Mat in, int sizeData) {
}
for (int x = 0; x < lowData.cols; x++) {
for (int y = 0; y < lowData.rows; y++) {
out.at<float>(j) += (float) lowData.at < unsigned
char > (x, y);
out.at<float>(j) += (float) lowData.at <unsigned char> (x, y);
j++;
}
}
@ -952,99 +951,56 @@ bool verifyRotatedPlateSizes(RotatedRect mr) {
return true;
}
//! use verify size to first generate candidates
Mat mserMatch(const Mat &src, Mat &match, const Color r,
std::vector<RotatedRect>& out_plateRect, std::vector<Rect>& out_charRect) {
std::vector<Mat> channelImages;
std::vector<int> flags;
Mat image = src;
std::vector<RotatedRect> plateRects;
std::vector<Rect> charRects;
// only conside blue plate
if (1) {
Mat grayImage;
cvtColor(src, grayImage, COLOR_BGR2GRAY);
channelImages.push_back(grayImage);
flags.push_back(0);
//Mat singleChannelImage;
//extractChannel(src, singleChannelImage, 2);
//channelImages.push_back(singleChannelImage);
//flags.push_back(0);
}
std::vector<std::vector<std::vector<Point>>> all_contours;
std::vector<std::vector<Rect>> all_boxes;
all_contours.resize(channelImages.size());
all_boxes.resize(channelImages.size());
std::vector<std::vector<Point>> all_contours;
std::vector<Rect> all_boxes;
for (int i = 0; i < (int)channelImages.size(); ++i)
{
Ptr<MSER> mser;
std::vector<CCharacter> charVec;
Mat channelImage = channelImages[i];
//int scale_size = 1600;
//double scale_ratio = 1;
//Mat image = scaleImage(channelImage, Size(scale_size, scale_size), scale_ratio);
Mat image = channelImage;
match = Mat::zeros(image.rows, image.cols, image.type());
Mat result = image.clone();
cvtColor(result, result, COLOR_GRAY2BGR);
int imageArea = image.rows * image.cols;
mser = MSER::create(1, 30, int(0.05 * imageArea));
mser->detectRegions(image, all_contours, all_boxes);
if (3 == flags[i]) {
mser = MSER::create(3, 30, int(0.05 * imageArea));
}
else {
mser = MSER::create(1, 30, int(0.05 * imageArea));
}
mser->detectRegions(image, all_contours[i], all_boxes[i]);
size_t size = all_contours[i].size();
size_t size = all_contours.size();
int char_index = 0;
for (size_t index = 0; index < size; index++) {
Rect rect = all_boxes[i][index];
std::vector<Point> contour = all_contours[i][index];
Rect rect = all_boxes[index];
std::vector<Point> contour = all_contours[index];
RotatedRect rrect = minAreaRect(Mat(contour));
if (verifyRotatedPlateSizes(rrect)) {
//cv::rectangle(result, rrect.boundingRect(), Scalar(0, 255, 0));
Point2f rect_points[4];
rrect.points(rect_points);
for (int j = 0; j < 4; j++)
line(result, rect_points[j], rect_points[(j + 1) % 4], Scalar(0, 255, 0), 1, 8);
plateRects.push_back(rrect);
}
if (verifyCharSizes(rect)) {
float aspect = float(rect.width) / float(rect.height);
Mat region = image(rect);
Mat binary_region;
threshold(region, binary_region, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
Mat charInput = preprocessChar(binary_region, 20);
std::string label = "";
float maxVal = -2.f;
// use mserMat
Mat mserMat = adaptive_image_from_points(contour, rect, Size(20, 20));
// use charMat
bool isCharacter = CharsIdentify::instance()->isCharacter(charInput, label, maxVal);
if (1)
{
std::stringstream ss(std::stringstream::in | std::stringstream::out);
ss << "resources/image/tmp/character" << char_index++ << ".jpg";
imwrite(ss.str(), mserMat);
}
//if (0)
//{
// std::stringstream ss(std::stringstream::in | std::stringstream::out);
// ss << "resources/image/tmp/character" << char_index++ << ".jpg";
// imwrite(ss.str(), mserMat);
//}
if (1) {
//match(rect) = min(max(0, int(maxVal * 255)),255);
@ -1053,7 +1009,7 @@ Mat mserMatch(const Mat &src, Mat &match, const Color r,
cv::rectangle(result, rect, Scalar(255, 0, 0));
Point center(rect.tl().x + rect.width / 2, rect.tl().y + rect.height / 2);
cv::circle(result, center, 3, Scalar(0, 255, 0), 2);
//cv::circle(result, center, 3, Scalar(0, 255, 0), 2);
charRects.push_back(rect);
out_charRect.push_back(rect);
@ -1066,9 +1022,7 @@ Mat mserMatch(const Mat &src, Mat &match, const Color r,
}
}
}
for (auto prect : plateRects) {
float areasum = 0.f;
int count = 0;
@ -1106,7 +1060,7 @@ Mat mserMatch(const Mat &src, Mat &match, const Color r,
if (ratio - 0.5f > 0 && count >= 5) {
std::cout << "ratio:" << ratio << std::endl;
std::cout << "count:" << count << std::endl;
cv::rectangle(result, prect.boundingRect(), Scalar(0, 255, 0));
//cv::rectangle(result, prect.boundingRect(), Scalar(0, 255, 0));
out_plateRect.push_back(prect);
}
}
@ -1115,7 +1069,6 @@ Mat mserMatch(const Mat &src, Mat &match, const Color r,
imshow("result", result);
waitKey(0);
}
}
return match;

@ -9,7 +9,7 @@ namespace easypr {
//! 获取垂直和水平的直方图图值
Mat getTheFeatures(Mat in) {
Mat getHistogram(Mat in) {
const int VERTICAL = 0;
const int HORIZONTAL = 1;
@ -49,7 +49,7 @@ void getHistogramFeatures(const Mat& image, Mat& features) {
Mat img_threshold;
threshold(grayImage, img_threshold, 0, 255,
CV_THRESH_OTSU + CV_THRESH_BINARY);
features = getTheFeatures(img_threshold);
features = getHistogram(img_threshold);
}
//! EasyPR的getFeatures回调函数

@ -85,9 +85,7 @@ int CPlateLocate::mserSearch(const Mat &src, const Color r, Mat &out,
vector<RotatedRect> &outRects, int index) {
Mat match_grey;
Mat result = src.clone();
// width值对最终结果影响很大可以考虑进行多次colorSerch每次不同的值
// 另一种解决方案就是在结果输出到SVM之前进行线与角的再纠正
cvtColor(result, result, COLOR_GRAY2BGR);
const int color_morph_width = 20;
const int color_morph_height = 5;
@ -179,6 +177,7 @@ int CPlateLocate::mserSearch(const Mat &src, const Color r, Mat &out,
Point center(charRect.tl().x + charRect.width / 2, charRect.tl().y + charRect.height / 2);
points.push_back(center);
cv::circle(result, center, 3, Scalar(0, 255, 0), 2);
if (charRect.area() - maxarea > 0.1f) {
maxrect = charRect;
maxarea = charRect.area();
@ -206,10 +205,24 @@ int CPlateLocate::mserSearch(const Mat &src, const Color r, Mat &out,
Rect rightRect(Point2f(rightPoint.x, rightPoint.y - maxrect.height / 2), maxrect.size());
cv::rectangle(result, leftRect, Scalar(255, 255, 0));
cv::rectangle(result, rightRect, Scalar(255, 255, 0));
/*vector<Mat> slideMat;
cv::rectangle(result, rightRect, Scalar(255, 255, 0));
int steplength = maxrect.width;
for (int step = - steplength / 2; step < steplength / 2; step++) {
int rightx = right + step;
Point2f rightPoint((float)rightx, k * (rightx - line[2]) + line[3]);
Rect slideRightRect(Point2f(rightPoint.x, rightPoint.y - maxrect.height / 2), maxrect.size());
Mat region = grayImage(slideRightRect);
Mat binary_region;
threshold(region, binary_region, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
Mat charInput = preprocessChar(binary_region, 20);
slideMat.push_back(charInput);
}*/
}
@ -962,21 +975,45 @@ int CPlateLocate::plateColorLocate(Mat src, vector<CPlate> &candPlates,
//! MSER plate locate
int CPlateLocate::plateMserLocate(Mat src, vector<CPlate> &candPlates, int index) {
std::vector<Mat> channelImages;
std::vector<int> flags;
// only conside blue plate
if (1) {
Mat grayImage;
cvtColor(src, grayImage, COLOR_BGR2GRAY);
channelImages.push_back(grayImage);
flags.push_back(0);
//Mat singleChannelImage;
//extractChannel(src, singleChannelImage, 2);
//channelImages.push_back(singleChannelImage);
//flags.push_back(0);
//channelImages.push_back(255 - grayImage);
//flags.push_back(1);
}
vector<RotatedRect> rects_mser_blue;
vector<CPlate> plates;
Mat src_b;
//// 查找蓝色车牌
//// 查找颜色匹配车牌
mserSearch(src, BLUE, src_b, rects_mser_blue, index);
for (size_t i = 0; i < channelImages.size(); ++i)
{
Mat channelImage = channelImages[i];
int scale_size = 1024;
double scale_ratio = 1;
Mat image = scaleImage(channelImage, Size(scale_size, scale_size), scale_ratio);
//// 进行抗扭斜处理
deskew(src, src_b, rects_mser_blue, plates);
for (size_t i = 0; i < plates.size(); i++) {
candPlates.push_back(plates[i]);
mserSearch(image, BLUE, src_b, rects_mser_blue, index);
}
//deskew(src, src_b, rects_mser_blue, plates);
//for (size_t i = 0; i < plates.size(); i++) {
// candPlates.push_back(plates[i]);
//}
return 0;
}

@ -101,7 +101,7 @@ cv::Ptr<cv::ml::TrainData> AnnTrain::tdata() {
auto chars_files = utils::getFiles(sub_folder);
for (auto file : chars_files) {
auto img = cv::imread(file, 0); // a grayscale image
auto fps = features(img, kPredictSize);
auto fps = charFeatures(img, kPredictSize);
samples.push_back(fps);
labels.push_back(i);

Loading…
Cancel
Save