EasyPR中主要涉及到蓝色底牌与黄色底牌、白色底牌的车牌识别,随着新能源车辆的发展,目前有很多绿色底牌的车牌,因此增加绿色车牌的识别。
EasyPR中关于车牌的识别,已经比较完善,这里主要涉及到三个地方的修改。
1.添加颜色
include/easypr/config.h
在自定义Color的枚举类中,添加 绿色,修改之后为:
enum Color { BLUE, YELLOW, WHITE, GREEN, UNKNOWN };
添加绿色识别
在OpenCV或其他软件中,识别颜色主要通过RGB映射到HSV空间,通过判断H、S、V的相关值来判断颜色的,主要原理可以参考:OpenCV颜色识别。修改之后的部分代码如下:
src/core/core_func.cpp
Mat colorMatch(const Mat &src, Mat &match, const Color r,
const bool adaptive_minsv) {
// if use adaptive_minsv
// min value of s and v is adaptive to h
const float max_sv = 255;
const float minref_sv = 64;
const float minabs_sv = 95; //95;
// H range of blue
const int min_blue = 100; // 100
const int max_blue = 140; // 140
// H range of yellow
const int min_yellow = 15; // 15
const int max_yellow = 40; // 40
// H range of white
const int min_white = 0; // 15
const int max_white = 30; // 40
//Louis add,green
// H range of green
const int min_green = 35; // 35
const int max_green = 80; // 80
Mat src_hsv;
// convert to HSV space
cvtColor(src, src_hsv, CV_BGR2HSV);
std::vector hsvSplit;
split(src_hsv, hsvSplit);
equalizeHist(hsvSplit[2], hsvSplit[2]);
merge(hsvSplit, src_hsv);
// match to find the color
int min_h = 0;
int max_h = 0;
switch (r) {
case BLUE:
min_h = min_blue;
max_h = max_blue;
break;
case YELLOW:
min_h = min_yellow;
max_h = max_yellow;
break;
case WHITE:
min_h = min_white;
max_h = max_white;
break;
//Louis add,green
case GREEN:
min_h = min_green;
max_h = max_green;
break;
default:
// Color::UNKNOWN
break;
}
float diff_h = float((max_h - min_h) / 2);
float avg_h = min_h + diff_h;
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;
}
int i, j;
uchar* p;
float s_all = 0;
float v_all = 0;
float count = 0;
for (i = 0; i < nRows; ++i) {
p = src_hsv.ptr(i);
for (j = 0; j < nCols; j += 3) {
int H = int(p[j]); // 0-180
int S = int(p[j + 1]); // 0-255
int V = int(p[j + 2]); // 0-255
s_all += S;
v_all += V;
count++;
bool colorMatched = false;
if (H > min_h && H < max_h) {
float Hdiff = 0;
if (H > avg_h)
Hdiff = H - avg_h;
else
Hdiff = avg_h - H;
float Hdiff_p = float(Hdiff) / diff_h;
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)
else
min_sv = minabs_sv; // add
if ((S > min_sv && S < max_sv) && (V > min_sv && V < max_sv))
colorMatched = true;
}
if (colorMatched == true) {
p[j] = 0;
p[j + 1] = 0;
p[j + 2] = 255;
}
else {
p[j] = 0;
p[j + 1] = 0;
p[j + 2] = 0;
}
}
}
// cout << "avg_s:" << s_all / count << endl;
// cout << "avg_v:" << v_all / count << endl;
// get the final binary
Mat src_grey;
std::vector hsvSplit_done;
split(src_hsv, hsvSplit_done);
src_grey = hsvSplit_done[2];
match = src_grey;
return src_grey;
}
其中RGB与HSV颜色识别对应的关系,可以参考:OpenCV中HSV颜色模型及颜色分量范围
增加字符限制
以前的车牌主要是7位字符,包括省 [A-Z].[5位字符] 的方式。但新能源车牌,后面5为字符变为6位字符,因此之前的判断方法不能够获取全部车牌,最好的情况也只能获得前面的7位字符。因此需要修改为:
src/core/chars_segment.cpp
int CCharsSegment::RebuildRect(const vector& vecRect,
vector& outRect, int specIndex) {
int count = 7;//Louis changed 6->7, for green plate car
for (size_t i = specIndex; i < vecRect.size() && count; ++i, --count) {
outRect.push_back(vecRect[i]);
}
return 0;
}
至此,可以识别绿色车牌。