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 ...
随机推荐
- setsockopt详解
Socket描述符选项[SOL_SOCKET] #include <sys/socket.h> int setsockopt( int socket, int level, int op ...
- java.lang.StackOverflowError
在开发中经常会遇到内存溢出的情况,大部分原因是因为:代码中有死循环.过度递归等情况 解决办法:看报错 找到是因为死循环还是过度递归,改掉即可 我的报错原因是使用了 new Gson.().toJson ...
- Delphi中Inputbox 和Inputquery 函数的使用
原文转自:http://blog.csdn.net/zengcong2013/article/details/18355959 inputbox的返回值是,你在输入框中输入的文字.而inputquer ...
- 1. [Vue warn]: Missing required prop: "value"
意思是说数据没有绑定,页面缺少value值.应该v-model进行数据绑定.
- python3下最简单的九九乘法表
def minus(): print("=========================九九乘法表===========================") x=1 y=1 wh ...
- 异常:Instantiation of bean failed; nested exception is java.lang.NoSuchMethodError: com.google.common.base.Preconditions.che ckState(ZLjava/lang/String;I)V
Instantiation of bean failed; nested exception is java.lang.NoSuchMethodError: com.google.common.bas ...
- redis 安装启动
1.解压 tar -zxvf redis文件 2. make 3. cp redis-server redis-cli /usr/local/redis cp redis.conf /usr/loca ...
- 使用spring-session共享springmvc项目的session
一.说在前面 spring mvc项目,使用nginx,tomcat部署. 之前没做session共享,而nginx采用sticky模块进行分发. 但发现有时不能正确地指向同一台服务器,从而导致ses ...
- 对BRD、MRD、PRD、FSD四类产品文档的理解
查阅相关文献并总结了在产品生命周期内比较重要的四类文档—BRD.MRD.PRD.FSD各自的含义以及用法. BRD 1.含义:BRD(business requirement document)— 商 ...
- 程序员常用字体(vs2008字体修改方案)
字体不仅是设计师手中重要的武器,对我们开发人员来说,字体的选择也有许多讲究,一个好的.适合展示代码的字体,应该具备以下要素: 等宽的字符 简洁.清晰并且规范的字符形状 支持ASCII码为128以上的扩 ...