1.3
Micooz 11 years ago
parent cfb743a3dc
commit 4a379d265c

@ -1,6 +1,6 @@
// 这个文件定义了EasyPR里所有plate判断的通用函数
// 所属命名空间为easypr
// 这个部分中的函数轻易不要改动
// 这个文件定义了EasyPR里所有plate判断的通用函数
// 所属命名空间为easypr
// 这个部分中的函数轻易不要改动
#include "../include/prep.h"
#include "../include/core_func.h"
@ -10,30 +10,30 @@ Namespace where all the C++ EasyPR functionality resides
*/
namespace easypr {
//! 根据一幅图像与颜色模板获取对应的二值图
//! 输入RGB图像, 颜色模板(蓝色、黄色)
//! 输出灰度图只有0和255两个值255代表匹配0代表不匹配
//! 根据一幅图像与颜色模板获取对应的二值图
//! 输入RGB图像, 颜色模板(蓝色、黄色)
//! 输出灰度图只有0和255两个值255代表匹配0代表不匹配
Mat colorMatch(const Mat& src, Mat& match, const Color r, const bool adaptive_minsv)
{
// S和V的最小值由adaptive_minsv这个bool值判断
// 如果为true则最小值取决于H值按比例衰减
// 如果为false则不再自适应使用固定的最小值minabs_sv
// 默认为false
// S和V的最小值由adaptive_minsv这个bool值判断
// 如果为true则最小值取决于H值按比例衰减
// 如果为false则不再自适应使用固定的最小值minabs_sv
// 默认为false
const float max_sv = 255;
const float minref_sv = 64;
const float minabs_sv = 95;
//blue的H范围
//blue的H范围
const int min_blue = 100; //100
const int max_blue = 140; //140
//yellow的H范围
//yellow的H范围
const int min_yellow = 15; //15
const int max_yellow = 40; //40
Mat src_hsv;
// 转到HSV空间进行处理颜色搜索主要使用的是H分量进行蓝色与黄色的匹配工作
// 转到HSV空间进行处理颜色搜索主要使用的是H分量进行蓝色与黄色的匹配工作
cvtColor(src, src_hsv, CV_BGR2HSV);
vector<Mat> hsvSplit;
@ -41,7 +41,7 @@ namespace easypr {
equalizeHist(hsvSplit[2], hsvSplit[2]);
merge(hsvSplit, src_hsv);
//匹配模板基色,切换以查找想要的基色
//匹配模板基色,切换以查找想要的基色
int min_h = 0;
int max_h = 0;
switch (r) {
@ -60,10 +60,10 @@ namespace easypr {
int channels = src_hsv.channels();
int nRows = src_hsv.rows;
//图像数据列需要考虑通道数的影响;
//图像数据列需要考虑通道数的影响;
int nCols = src_hsv.cols * channels;
if (src_hsv.isContinuous())//连续存储的数据,按一行处理
if (src_hsv.isContinuous())//连续存储的数据,按一行处理
{
nCols *= nRows;
nRows = 1;
@ -99,9 +99,9 @@ namespace easypr {
float Hdiff_p = float(Hdiff) / diff_h;
// S和V的最小值由adaptive_minsv这个bool值判断
// 如果为true则最小值取决于H值按比例衰减
// 如果为false则不再自适应使用固定的最小值minabs_sv
// S和V的最小值由adaptive_minsv这个bool值判断
// 如果为true则最小值取决于H值按比例衰减
// 如果为false则不再自适应使用固定的最小值minabs_sv
float min_sv = 0;
if (true == adaptive_minsv)
min_sv = minref_sv - minref_sv / 2 * (1 - Hdiff_p); // inref_sv - minref_sv / 2 * (1 - Hdiff_p)
@ -124,7 +124,7 @@ namespace easypr {
//cout << "avg_s:" << s_all / count << endl;
//cout << "avg_v:" << v_all / count << endl;
// 获取颜色匹配后的二值灰度图
// 获取颜色匹配后的二值灰度图
Mat src_grey;
vector<Mat> hsvSplit_done;
split(src_hsv, hsvSplit_done);
@ -137,9 +137,9 @@ namespace easypr {
bool bFindLeftRightBound1(Mat& bound_threshold,int& posLeft,int& posRight)
{
//从两边寻找边界
//从两边寻找边界
int span = bound_threshold.rows*0.2;
//左边界检测
//左边界检测
for (int i=0; i < bound_threshold.cols-span-1;i+=3)
{
int whiteCount = 0;
@ -162,7 +162,7 @@ namespace easypr {
}
span = bound_threshold.rows*0.2;
//右边界检测
//右边界检测
for (int i=bound_threshold.cols-1; i > span;i-=2)
{
int whiteCount = 0;
@ -204,9 +204,9 @@ namespace easypr {
bool bFindLeftRightBound(Mat& bound_threshold,int& posLeft,int& posRight)
{
//从两边寻找边界
//从两边寻找边界
int span = bound_threshold.rows*0.2;
//左边界检测
//左边界检测
for (int i=0; i < bound_threshold.cols-span-1;i+=2)
{
int whiteCount = 0;
@ -229,7 +229,7 @@ namespace easypr {
}
span = bound_threshold.rows*0.2;
//右边界检测
//右边界检测
for (int i=bound_threshold.cols-1; i > span;i-=2)
{
int whiteCount = 0;
@ -262,9 +262,9 @@ namespace easypr {
bool bFindLeftRightBound2(Mat& bound_threshold,int& posLeft,int& posRight)
{
//从两边寻找边界
//从两边寻找边界
int span = bound_threshold.rows*0.2;
//左边界检测
//左边界检测
for (int i=0; i < bound_threshold.cols-span-1;i+=3)
{
int whiteCount = 0;
@ -287,7 +287,7 @@ namespace easypr {
}
span = bound_threshold.rows*0.2;
//右边界检测
//右边界检测
for (int i=bound_threshold.cols-1; i > span;i-=3)
{
int whiteCount = 0;
@ -318,12 +318,12 @@ namespace easypr {
}
//! 判断一个车牌的颜色
//! 输入车牌mat与颜色模板
//! 返回true或fasle
//! 判断一个车牌的颜色
//! 输入车牌mat与颜色模板
//! 返回true或fasle
bool plateColorJudge(const Mat& src, const Color r, const bool adaptive_minsv)
{
// 判断阈值
// 判断阈值
const float thresh = 0.45;
Mat src_gray;
@ -339,7 +339,7 @@ namespace easypr {
}
//getPlateType
//判断车牌的类型
//判断车牌的类型
Color getPlateType(const Mat& src, const bool adaptive_minsv)
{
if (plateColorJudge(src, BLUE, adaptive_minsv) == true) {
@ -394,9 +394,9 @@ namespace easypr {
}
}
//去除车牌上方的钮钉
//计算每行元素的阶跃数如果小于X认为是柳丁将此行全部填0涂黑
//X的推荐值为可根据实际调整
//去除车牌上方的钮钉
//计算每行元素的阶跃数如果小于X认为是柳丁将此行全部填0涂黑
//X的推荐值为可根据实际调整
bool clearLiuDing(Mat& img)
{
@ -431,7 +431,7 @@ namespace easypr {
}
}
////这样的不是车牌
////这样的不是车牌
if (iCount*1.0/img.rows < 0.5)
{
return false;
@ -491,7 +491,7 @@ namespace easypr {
}
//ok,找到上下边界
//ok,找到上下边界
for (int i = mask.rows-1; i >= mask.rows/2; i--)
{
int jumpCount = 0;
@ -572,7 +572,7 @@ namespace easypr {
return thresholdV;
}
//! 直方图均衡
//! 直方图均衡
Mat histeq(Mat in)
{
Mat out(in.size(), in.type());
@ -609,7 +609,7 @@ namespace easypr {
int numCols=vhist.cols+hhist.cols+lowData.cols*lowData.cols;
Mat out=Mat::zeros(1,numCols,CV_32F);
//Asign values to feature,ANN的样本特征为水平、垂直直方图和低分辨率图像所组成的矢量
//Asign values to feature,ANN的样本特征为水平、垂直直方图和低分辨率图像所组成的矢量
int j=0;
for(int i=0; i<vhist.cols; i++)
{
@ -675,7 +675,7 @@ namespace easypr {
}
}
// !获取垂直和水平方向直方图
// !获取垂直和水平方向直方图
Mat ProjectedHistogram(Mat img, int t)
{
int sz = (t) ? img.rows : img.cols;
@ -684,7 +684,7 @@ namespace easypr {
for (int j = 0; j<sz; j++){
Mat data = (t) ? img.row(j) : img.col(j);
mhist.at<float>(j) =countNonZero(data); //统计这一行或一列中非零元素的个数并保存到mhist中
mhist.at<float>(j) =countNonZero(data); //统计这一行或一列中非零元素的个数并保存到mhist中
}
//Normalize histogram
@ -692,7 +692,7 @@ namespace easypr {
minMaxLoc(mhist, &min, &max);
if (max>0)
mhist.convertTo(mhist, -1, 1.0f / max, 0);//用mhist直方图中的最大值归一化直方图
mhist.convertTo(mhist, -1, 1.0f / max, 0);//用mhist直方图中的最大值归一化直方图
return mhist;
}

Loading…
Cancel
Save