一、简介

对车牌颜色进行识别,可能大部分人首先想到的是RGB模型, 但是此处RGB模型有一定的局限性,譬如蓝色,其值是255,还需要另外两个分量都为0,不然很有可能你得到的值是白色。黄色更麻烦,它是由红色和绿色组合而成的,这意味着你需要考虑两个变量的配比问题。这些问题让选择 RGB 模型进行判断的难度大到难以接受的地步。

HSV(Hue, Saturation, Value)是根据颜色的直观特性创建的一种颜色空间,也称六角锥体模型(Hexcone Model)。这个模型中颜色的参数分别是:色度(H),饱和度(S),亮度(V)。
  • 色度H:用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。
  • 饱和度S:取值范围为0.0~1.0;
  • 亮度V:取值范围为0.0(黑色)~1.0(白色)。
RGB和CMY颜色模型都是面向硬件的,而HSV(Hue Saturation Value)颜色模型是面向用户的。
HSV模型的三维表示从RGB立方体演化而来。设想从RGB沿立方体对角线的白色顶点向黑色顶点观察,就可以看到立方体的六边形外形。六边形边界表示色彩,水平轴表示纯度,明度沿垂直轴测量。

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):车牌定位之颜色定位的更多相关文章

  1. EasyPR源码剖析(5):车牌定位之偏斜扭转

    一.简介 通过颜色定位和Sobel算子定位可以计算出一个个的矩形区域,这些区域都是潜在车牌区域,但是在进行SVM判别是否是车牌之前,还需要进行一定的处理.主要是考虑到以下几个问题: 1.定位区域存在一 ...

  2. EasyPR源码剖析(2):车牌定位

    上一篇主要介绍了车牌识别的整体框架和流程,车牌识别主要划分为了两个过程:即车牌检测和字符识别,而车牌识别的核心环节就是这一节主要介绍的车牌定位,即 Plate Locate.车牌定位主要是将图片中有可 ...

  3. EasyPR源码剖析(1):概述

    EasyPR(Easy to do Plate Recognition)是本人在opencv学习过程中接触的一个开源的中文车牌识别系统,项目Git地址为https://github.com/liuru ...

  4. EasyPR源码剖析(4):车牌定位之Sobel算子定位

    一.简介 sobel算子主要是用于获得数字图像的一阶梯度,常见的应用是边缘检测. Ⅰ.水平变化: 将 I 与一个奇数大小的内核进行卷积.比如,当内核大小为3时, 的计算结果为: Ⅱ.垂直变化: 将: ...

  5. EasyPR源码剖析(7):车牌判断之SVM

    前面的文章中我们主要介绍了车牌定位的相关技术,但是定位出来的相关区域可能并非是真实的车牌区域,EasyPR通过SVM支持向量机,一种机器学习算法来判定截取的图块是否是真的“车牌”,本节主要对相关的技术 ...

  6. EasyPR源码剖析(6):车牌判断之LBP特征

    一.LBP特征 LBP指局部二值模式,英文全称:Local Binary Pattern,是一种用来描述图像局部特征的算子,LBP特征具有灰度不变性和旋转不变性等显著优点. 原始的LBP算子定义在像素 ...

  7. EasyPR源码剖析(8):字符分割

    通过前面的学习,我们已经可以从图像中定位出车牌区域,并且通过SVM模型删除“虚假”车牌,下面我们需要对车牌检测步骤中获取到的车牌图像,进行光学字符识别(OCR),在进行光学字符识别之前,需要对车牌图块 ...

  8. EasyPR源码剖析(9):字符识别

    在上一篇文章的介绍中,我们已经通过相应的字符分割方法,将车牌区域进行分割,得到7个分割字符图块,接下来要做的就是将字符图块放入训练好的神经网络模型,通过模型来预测每个图块所表示的具体字符.神经网络的介 ...

  9. HashMap源码剖析

    HashMap源码剖析 无论是在平时的练习还是项目当中,HashMap用的是非常的广,真可谓无处不在.平时用的时候只知道HashMap是用来存储键值对的,却不知道它的底层是如何实现的. 一.HashM ...

随机推荐

  1. Android开发 静态static类与static方法持有Context是否导致内存泄露的疑问

    简述 在Android开发的过程中,难免会使用单例模式或者静态方法工具类.我们会让它们持有一些外部的Context或者View一般有以下几种情况: 单例模式,类的全局变量持有Context 或 Vie ...

  2. 数据库alert报错:ORA-00202、ORA-15081、ORA-27072

    思路分析: 1.发现数据库宕机,检查alert日志发现如下出现控制文件:I/O错误 Thu Apr 11 06:40:14 2019WARNING: Read Failed. group:2 disk ...

  3. mysql 5.5数据导入5.7 Failed - Error on Table user - 1067 - Invalid default value for 'CREATE_date'

    表结构是这样 DROP TABLE IF EXISTS `user`;CREATE TABLE `user` (....省略了一些无关紧要的字段 `CREATE_DATE_` timestamp NO ...

  4. maven dependency的版本冲突问题

    在改造一个旧项目中,遇到各种问题. 旧项目有十多个模块,因为没有一个统一的父pom,它们对第三方的jar的版本没有统一. 虽然也存在公共的依赖模块,比如commons.util,但是,我们的模块中,有 ...

  5. jQuery入门基础(选择器)

    一.jQuery简介 jQuery 是一个 JavaScript 库. jQuery 极大地简化了 JavaScript 编程. jQuery 库位于一个 JavaScript 文件中,其中包含了所有 ...

  6. sql语句应用

    laravel5.6框架中用到的sql语句 //排序 $data=DB::table('admin')->select(array('id','name','password'))->or ...

  7. XML文档的生成和解析操作方法

    XML文档和JSon文档同为网络传输中的数据格式,JSon的解析和创建已经在新浪微博的使用中相当熟悉,故仅仅记载XML文档的相关方法. 关于XML文档: 1.一种便于编辑和传输的数据文件格式 2.xm ...

  8. js:基于原生js的上啦下啦刷新功能

    链接:https://www.jianshu.com/p/a8392115e6f0演示地址:http://wonghan.cn/iscroll-demo/html:<body> <d ...

  9. 面试必备:ArrayList源码解析(JDK8)

    面试必备:ArrayList源码解析(JDK8) https://blog.csdn.net/zxt0601/article/details/77281231 概述很久没有写博客了,准确的说17年以来 ...

  10. SVN使用教程总结(转载)

    SVN简介: 为什么要使用SVN? 程序员在编写程序的过程中,每个程序员都会生成很多不同的版本,这就需要程序员有效的管理代码,在需要的时候可以迅速,准确取出相应的版本. Subversion是什么? ...