EasyPR源码剖析(3):车牌定位之颜色定位
一、简介
对车牌颜色进行识别,可能大部分人首先想到的是RGB模型, 但是此处RGB模型有一定的局限性,譬如蓝色,其值是255,还需要另外两个分量都为0,不然很有可能你得到的值是白色。黄色更麻烦,它是由红色和绿色组合而成的,这意味着你需要考虑两个变量的配比问题。这些问题让选择 RGB 模型进行判断的难度大到难以接受的地步。
- 色度H:用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。
- 饱和度S:取值范围为0.0~1.0;
- 亮度V:取值范围为0.0(黑色)~1.0(白色)。
H 分量是 HSV 模型中唯一跟颜色本质相关的分量。 只要固定了 H 的值, 并且保持 S 和 V 分量不太小,那么表现的颜色就会基本固定。
一般对颜色空间的图像进行有效处理都是在HSV空间进行的,然后对于基本色中对应的HSV分量需要给定一个严格的范围,下面是通过实验计算的模糊范围(准确的范围在网上都没有给出)。
H: 0— 180
S: 0— 255
V: 0— 255
读取一张图片或从视频读取一帧图像,可以用下面的函数转为HSV模型。
cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV);
然后对彩色图像做直方图均衡化,因为读取的是彩色图,直方图均衡化需要在HSV空间中进行。
split(imgHSV, hsvSplit);
equalizeHist(hsvSplit[2],hsvSplit[2]);
merge(hsvSplit,imgHSV);
接着就是进行颜色检测
inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), imgThresholded);
inRange()函数进行颜色检测,这个函数的作用就是检测src图像的每一个像素是不是在lowerb和upperb之间,如果是,这个像素就设置为255,并保存在dst图像中,否则为0。
二、颜色定位
颜色定位主要处理函数为 plateColorLocate() ,具体代码如下所示
int CPlateLocate::plateColorLocate(Mat src, vector<CPlate> &candPlates,int index) {
vector<RotatedRect> rects_color_blue;
rects_color_blue.reserve();
vector<RotatedRect> rects_color_yellow;
rects_color_yellow.reserve(); vector<CPlate> plates_blue;
plates_blue.reserve();
vector<CPlate> plates_yellow;
plates_yellow.reserve(); Mat src_clone = src.clone(); Mat src_b_blue;
Mat src_b_yellow;
#pragma omp parallel sections
{
#pragma omp section
{
colorSearch(src, BLUE, src_b_blue, rects_color_blue);
deskew(src, src_b_blue, rects_color_blue, plates_blue, true, BLUE);
}
#pragma omp section
{
colorSearch(src_clone, YELLOW, src_b_yellow, rects_color_yellow);
deskew(src_clone, src_b_yellow, rects_color_yellow, plates_yellow, true, YELLOW);
}
} candPlates.insert(candPlates.end(), plates_blue.begin(), plates_blue.end());
candPlates.insert(candPlates.end(), plates_yellow.begin(), plates_yellow.end()); return ;
}
这里为了加快计算机的计算速率,采用了OpenMP技术,OpenMP是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受,用于共享内存并行系统的多处理器程序设计的一套指导性编译处理方案。通过并行计算,分别进行蓝色和黄色车牌的处理。其中两个主要处理函数 colorSearch() 和 deskew()分别对图片进行颜色匹配和偏斜扭转。
colorSearch()主要是根据上文介绍的HSV模型,进行相关颜色定位,然后依据常见的图像处理方法进行处理,例如阈值分割,形态学处理和轮廓查找等。具体代码如下所示:
int CPlateLocate::colorSearch(const Mat &src, const Color r, Mat &out,
vector<RotatedRect> &outRects) {
Mat match_grey; // width is important to the final results; const int color_morph_width = ;
const int color_morph_height = ; colorMatch(src, match_grey, r, false); Mat src_threshold;
threshold(match_grey, src_threshold, , ,
CV_THRESH_OTSU + CV_THRESH_BINARY); Mat element = getStructuringElement(
MORPH_RECT, Size(color_morph_width, color_morph_height));
morphologyEx(src_threshold, src_threshold, MORPH_CLOSE, element); src_threshold.copyTo(out); vector<vector<Point>> contours; findContours(src_threshold,
contours, // a vector of contours
CV_RETR_EXTERNAL,
CV_CHAIN_APPROX_NONE); // all pixels of each contours vector<vector<Point>>::iterator itc = contours.begin();
while (itc != contours.end()) {
RotatedRect mr = minAreaRect(Mat(*itc)); if (!verifySizes(mr))
itc = contours.erase(itc);
else {
++itc;
outRects.push_back(mr);
}
} return ;
}
EasyPR中的colorMatch()函数比较复杂,读者可以简单理解为用inRange函数对图像hsv空间进行处理,得到颜色过滤后的图像。(其实colotMatch函数中对hsv模型中的s和v根据h的值进行自适应变化),进行阈值分割后,采用了形态学图像处理,内核为一个 10X2矩形,需要注意的是,内核的大小对最终的结果有很大的影响。对寻找到的轮廓,先进性尺寸验证,不符合尺寸的轮廓直接去除。尺寸验证调用函数 verifySizes() 。尺寸验证函数主要是对轮廓的长度和宽度,还有长宽比做了限制,以过滤掉大部分的明显非车牌的轮廓区域。
EasyPR源码剖析(3):车牌定位之颜色定位的更多相关文章
- EasyPR源码剖析(5):车牌定位之偏斜扭转
一.简介 通过颜色定位和Sobel算子定位可以计算出一个个的矩形区域,这些区域都是潜在车牌区域,但是在进行SVM判别是否是车牌之前,还需要进行一定的处理.主要是考虑到以下几个问题: 1.定位区域存在一 ...
- EasyPR源码剖析(2):车牌定位
上一篇主要介绍了车牌识别的整体框架和流程,车牌识别主要划分为了两个过程:即车牌检测和字符识别,而车牌识别的核心环节就是这一节主要介绍的车牌定位,即 Plate Locate.车牌定位主要是将图片中有可 ...
- EasyPR源码剖析(1):概述
EasyPR(Easy to do Plate Recognition)是本人在opencv学习过程中接触的一个开源的中文车牌识别系统,项目Git地址为https://github.com/liuru ...
- EasyPR源码剖析(4):车牌定位之Sobel算子定位
一.简介 sobel算子主要是用于获得数字图像的一阶梯度,常见的应用是边缘检测. Ⅰ.水平变化: 将 I 与一个奇数大小的内核进行卷积.比如,当内核大小为3时, 的计算结果为: Ⅱ.垂直变化: 将: ...
- EasyPR源码剖析(7):车牌判断之SVM
前面的文章中我们主要介绍了车牌定位的相关技术,但是定位出来的相关区域可能并非是真实的车牌区域,EasyPR通过SVM支持向量机,一种机器学习算法来判定截取的图块是否是真的“车牌”,本节主要对相关的技术 ...
- EasyPR源码剖析(6):车牌判断之LBP特征
一.LBP特征 LBP指局部二值模式,英文全称:Local Binary Pattern,是一种用来描述图像局部特征的算子,LBP特征具有灰度不变性和旋转不变性等显著优点. 原始的LBP算子定义在像素 ...
- EasyPR源码剖析(8):字符分割
通过前面的学习,我们已经可以从图像中定位出车牌区域,并且通过SVM模型删除“虚假”车牌,下面我们需要对车牌检测步骤中获取到的车牌图像,进行光学字符识别(OCR),在进行光学字符识别之前,需要对车牌图块 ...
- EasyPR源码剖析(9):字符识别
在上一篇文章的介绍中,我们已经通过相应的字符分割方法,将车牌区域进行分割,得到7个分割字符图块,接下来要做的就是将字符图块放入训练好的神经网络模型,通过模型来预测每个图块所表示的具体字符.神经网络的介 ...
- HashMap源码剖析
HashMap源码剖析 无论是在平时的练习还是项目当中,HashMap用的是非常的广,真可谓无处不在.平时用的时候只知道HashMap是用来存储键值对的,却不知道它的底层是如何实现的. 一.HashM ...
随机推荐
- LeetCode 101. Symmetric Tree 判断对称树 C++
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For e ...
- 分布式一致性算法2PC和3PC
为了解决分布式一致性问题,产生了不少经典的分布式一致性算法,本文将介绍其中的2PC和3PC.2PC即Two-Phase Commit,译为二阶段提交协议.3PC即Three-Phase Commit, ...
- c语言中的利用函数实现交换两个字符,交换两个字符串
c语言交换两个字符: 方法一:利用指针传址,效率比较高 void swap(int *a,int *b) { int temp; temp = *a; *a = *b; *b = temp } 方法二 ...
- java实现HTTP Basic认证
这两天一直在调试EMQ的API,通过HTTP的GET请求,可以查询到订阅列表信息,在浏览器中测试时,需要输入用户名和密码,然后才能显示出结果,输错或者不输入会返回401错误. 通过浏览器输入用户名和密 ...
- python3 字典update与deepcopy
问题概述: 在码代码中,需要保存一个字典,用的update,后来发现update的值会随着原字典值得变化而变化. 而后使用deepcopy来保存字典. update a = {1:{2:3}}b= { ...
- eclipse 构建 jpa project 所需的用户库(vendor: EclipseLink)
Eclipse 构建 JPA Project 时,需要指定 JPA的实现,如:下图中的EclipseLink 2.7.3,这其实是一个自定义的用户库. 看看,这个用户库包含persistence接口和 ...
- 常用mvn坐标
mysql-connector <dependency> <groupId>mysql</groupId> <artifactId>mysql-conn ...
- Java解法-两数相加(Add Two Numbers)
问题 给出两个非空的链表用来表示两个非负的整数.其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和. ...
- 用word发布CSDN文章
目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...
- JavaScript Array some() 方法
some 判断数组中是否至少有一个元素满足条件 只要有一个满足就返回true 只有都不满足时才返回false 语法: array.some(function(value,index,array),th ...