车牌识别之颜色选取

车牌定位是车牌识别中第一步,也是最重要的一步。

由于中国车牌种类多样,颜色不一, 再加上车牌经常有污损,以及车牌周围干扰因素太多,都成为了车牌定位的难点。

这里首先使用最简单算法来描述车牌定位,以及他的缺陷和改进。

一、投影法

1、车辆图像信息获取


2、HSV颜色转换

把RGB数据转换成HSV空间图像数据

hsvzation(image,hsv,width,height);


3、HSV颜色过滤

设置蓝色车牌底色阈值范围,进行颜色过滤

蓝色车牌

H值范围:190 ~ 245

S值范围: 0.35 ~ 1

V值范围: 0.3 ~ 1

过滤后图像如下:



4、噪声处理

过滤后,一般要进行去噪处理,这里早点不明显,如果车牌周围有蓝色物体,噪点就非常明显了

这里使用平均去噪,一些孤立白点将被去除,效果如下:



5、边缘检测

去噪后,进行边缘检测,边缘检测的目的就是为了突出车牌信息的突变,因为车牌背景和字体颜色区分开了;

这样做的目的也是为了防止周围有和车牌底色相同颜色的物体干扰,尤其是车辆颜色,因为经过边缘检测后车体颜色没有那么多跳变干扰或者与车牌跳变规律不一样,这样就可以滤去车体颜色,去除干扰



6、确定车牌位置

通过水平投影和垂直投影确定车牌位置。

这里投影方法有很大缺陷,在车牌周围除了车辆还有其他背景信息时尤为明显,这在下面的另一种方法中改善



7、截取车牌图像



二、投影法定位缺陷示例

1、读取复杂背景的车牌图像



2、HSV滤波

HSV过滤后可以看到明显的干扰信息,车辆后面的栏杆,和车辆同样的颜色



3、均值去噪

去噪后,虽然大部分噪点都去除了,但是栏杆依然清晰



4、边缘检测

边缘检测后的图像,车牌区域的形状特征,给我们解决投影缺陷的一些启示



5,、 投影后错误的定位



6、车牌提取错误

后半块车身,比例也不符合车牌特征



由此看见,在复杂背景的车牌识别中,全局投影就无法抑制干扰,在下面黄色车牌示例中就更加明显;

投影法简单,但只是在只有整体车辆信息,没有复杂背景信息的时候才可以使用。


三、基于候选区域判断方法

这个方法放弃了投影,直接遍历整个图像信息,检查每个联通域的长度和宽度,当符合车牌的宽高比时,才选定为候选区域,由后面处理流程进行处理,来判断是否能够提取正常的字符。


前两个步骤还是同上面一样的。

1、HSV空间转换


2、均值去噪



3、水平膨胀

目的:尽可能的形成连通域



4、边缘检测

也可以不用边缘检测,这里主要考虑到 尽量减少 图像白点 遍历中的运算



5、候选区域筛选

候选区域筛选, 这是区别投影方法的主要部分,

从上图可以看出有几个候选区域,大概有4块, 而中间的车牌有明显矩形特征,符合一定的长宽比例, 其他三块区域不具备这样的特征,在筛选的过程中予以舍弃。

筛选的方法采用 深度优先遍历, 当遇到连通域时,记录他的长度和高度,并设定阈值,当符合长宽比时,才会选中为候选区域,否则予以舍弃,当然还可以添加别的算法,比如检测跳变,毕竟符合这一比率的不一定就是车牌区域。

下图中黄框就是筛选后的区域:



连通域筛选函数如下:

[cpp] view plaincopy
  1. int find_connected_region_location(struct BMP_img *img, unsigned char *src, int xthreashold, int ythreashold, float rateLow, float rateHigh)  
  2. {  
  3.     int i,j;  
  4.     int x1, y1, x2, y2;  
  5.     int width;  
  6.     int height;  
  7.     unsigned char *temp;  
  8.     //int queue_count;  
  9.     int head, rear;  
  10.     struct XY_Queue *queue;  
  11.     static int direction[4][2]={{1, 0}, {-1, 0}, {0, 1}, {0, -1}};  
  12.   
  13.     width = img->width;  
  14.     height = img->height;  
  15.   
  16.     queue = (struct XY_Queue *)malloc(sizeof(struct XY_Queue) * width * height);  
  17.   
  18.     temp = (unsigned char *)malloc(width * height * sizeof(unsigned char));  
  19.   
  20.     if(temp == NULL)  
  21.     {  
  22.         printf("find_connected_region_location mem alloc fail\n");  
  23.         return -1;  
  24.     }  
  25.     memcpy(temp, src, width * height);  
  26.   
  27.     head = rear = 0;  
  28.     img->region_num = 0;  
  29.   
  30.     for(i = 0; i < height; i++)  
  31.         for(j = 0; j < width; j++)  
  32.     {  
  33.         if(temp[i * width + j] == 255)  
  34.         {  
  35.                       
  36.             queue[rear].x = j;  
  37.             queue[rear].y = i;  
  38.             rear ++;  
  39.             temp[i * width + j] = 0;  
  40.   
  41.             img->pre_region[img->region_num].x1 = j;  
  42.             img->pre_region[img->region_num].x2 = j;  
  43.             img->pre_region[img->region_num].y1 = i;  
  44.             img->pre_region[img->region_num].y2 = i;  
  45.   
  46.             if(img->region_num > CAN_REGION_NUM)  
  47.             {  
  48.                 printf("over the CAN_REGION_NUM\n");  
  49.                 return -1;  
  50.             }  
  51.   
  52.             while(head < rear)  
  53.             {  
  54.                 x1 = queue[head].x;  
  55.                 y1 = queue[head].y;  
  56.                 head ++;  
  57.   
  58.                 if(x1 < img->pre_region[img->region_num].x1)  
  59.                     img->pre_region[img->region_num].x1 = x1;  
  60.                 else if(x1 > img->pre_region[img->region_num].x2)  
  61.                     img->pre_region[img->region_num].x2 = x1;  
  62.                 if(y1 < img->pre_region[img->region_num].y1)  
  63.                     img->pre_region[img->region_num].y1 = y1;  
  64.                 else if(y1 > img->pre_region[img->region_num].y2)  
  65.                     img->pre_region[img->region_num].y2 = y1;  
  66.                   
  67.       
  68.                 for(i = 0; i < 4; i++)  
  69.                 {  
  70.                     x2 = x1 + direction[i][0];  
  71.                     y2 = y1 + direction[i][1];  
  72.   
  73.                     if(x2 > 0 && x2 < width && y2 > 0 && y2 < height && temp[y2 * width + x2])  
  74.                     {  
  75.                         temp[y2 * width + x2] = 0;  
  76.                         queue[rear].x = x2;  
  77.                         queue[rear].y = y2;  
  78.                         rear ++;  
  79.                     }  
  80.               
  81.                 }  
  82.             }  
  83.             if((img->pre_region[img->region_num].x2 - img->pre_region[img->region_num].x1 > xthreashold) && (img->pre_region[img->region_num].y2 - img->pre_region[img->region_num].y1 > ythreashold))  
  84.             {  
  85.   
  86.                 img->pre_region[img->region_num].width = img->pre_region[img->region_num].x2 - img->pre_region[img->region_num].x1 + 1;  
  87.                 img->pre_region[img->region_num].height = img->pre_region[img->region_num].y2 - img->pre_region[img->region_num].y1 + 1;  
  88.                 img->pre_region[img->region_num].rate = (float)img->pre_region[img->region_num].width/img->pre_region[img->region_num].height;  
  89.                 if((img->pre_region[img->region_num].width < img->width / 2) && (img->pre_region[img->region_num].height < img->height / 2))  
  90.                 if((img->pre_region[img->region_num].rate > rateLow) && (img->pre_region[img->region_num].rate < rateHigh))  
  91.                 {  
  92.                     if(img->pre_region[img->region_num].x2 + PRE_LOCATION_BIAS > img->width)  
  93.                             img->pre_region[img->region_num].x2 = img->width;  
  94.                     else  
  95.                             img->pre_region[img->region_num].x2 += PRE_LOCATION_BIAS;  
  96.                     if(img->pre_region[img->region_num].x1 - PRE_LOCATION_BIAS < 0)  
  97.                             img->pre_region[img->region_num].x1 = 0;  
  98.                     else  
  99.                             img->pre_region[img->region_num].x1 -= PRE_LOCATION_BIAS;  
  100.                     if(img->pre_region[img->region_num].y2 + PRE_LOCATION_BIAS > img->height)  
  101.                             img->pre_region[img->region_num].y2 = img->height;  
  102.                     else  
  103.                             img->pre_region[img->region_num].y2 += PRE_LOCATION_BIAS;  
  104.                     if(img->pre_region[img->region_num].y1 - PRE_LOCATION_BIAS < 0)  
  105.                             img->pre_region[img->region_num].y1 = 0;  
  106.                     else  
  107.                             img->pre_region[img->region_num].y1 -= PRE_LOCATION_BIAS;  
  108.   
  109.                     img->pre_region[img->region_num].width = img->pre_region[img->region_num].x2 - img->pre_region[img->region_num].x1 + 1;  
  110.                     img->pre_region[img->region_num].height = img->pre_region[img->region_num].y2 - img->pre_region[img->region_num].y1 + 1;  
  111.               
  112.                     img->region_num++;  
  113.                 }  
  114.             }  
  115.         }  
  116.           
  117.           
  118.     }  
  119.     free(temp);  
  120.     temp = NULL;  
  121.     return 0;  
  122. }  

6、截取车牌区域图像




四、黄色车牌检测

1、车辆图像信息



2、HSV过滤分割

由于车牌颜色 与 车辆颜色一直,出现大量噪声信息,全局投影已不可能分割出车牌信息了,

这里只是 利用候选区域长宽比来进行矩形分割,肯定会出现一些符合比例但是不是车牌的区域,必须在后面的处理中加以区分或者添加判断跳变规律的函数



3、去噪



4、 膨胀


6、边缘检测



7、候选区域 连通域筛选

从图中可以看到黄框 部分即是符合候选区域的地方



8、截取候选区域

此候选区域只是符合长宽比,需要另行处理 除去不是车牌的区域



五、小结

车牌定位比较复杂,但对于车牌识别来说,最为重要,我认为它是影响车牌识别最大因素。虽然复杂,但是方法多种多样。

这里仅此个人爱好和研究,希望各位朋友继续提出批评和建议,大家的鼓励给了我坚持下去的勇气。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/387657.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python - 排序( 插入, 冒泡, 快速, 二分 )

插入排序 算法分析 两次循环, 大循环对队列中的每一个元素拿出来作为小循环的裁定对象 小循环对堆当前循环对象在有序队列中寻找插入的位置 性能参数 空间复杂度  O(1) 时间复杂度  O(n^2) 详细代码解读 import randomdef func(l):# 外层循环: 对应遍历所有的无序数据for i…

[EmguCV|C#]使用CvInvoke自己繪製色彩直方圖-直方圖(Hitsogram)系列(4)

2014-02-0610325 0C# 檢舉文章 過年結束了&#xff0c;雖然還是學生所以其實還有兩個禮拜的假期&#xff0c;不過為了不讓自己發慌&#xff0c;趁著假期多利用充實自己&#xff0c;所以提早回到開工狀態&#xff0c;而這次總算要把一直說的自己動手繪製猜色直方圖文章寫出。 …

轮廓的查找、表达、绘制、特性及匹配(How to Use Contour? Find, Component, Construct, Features Match)

前言 轮廓是构成任何一个形状的边界或外形线。前面讲了如何根据色彩及色彩的分布&#xff08;直方图对比和模板匹配&#xff09;来进行匹配&#xff0c;现在我们来看看如何利用物体的轮廓。包括以下内容&#xff1a;轮廓的查找、表达方式、组织方式、绘制、特性、匹配。 查…

itcast-ssh-crm实践

分析 BaseDao 文件上传 转载于:https://www.cnblogs.com/hellowq/p/10209761.html

分类器大牛们

David Lowe&#xff1a;Sift算法的发明者&#xff0c;天才。 Rob Hess&#xff1a;sift的源码OpenSift的作者&#xff0c;个人主页上有openSift的下载链接&#xff0c;Opencv中sift的实现&#xff0c;也是参考这个。 Koen van de Sande&#xff1a;作者给出了sift,densesift,co…

利用python脚本程序监控文件被修改

需求&#xff1a;利用python编写监控程序&#xff0c;监控一个文件目录&#xff0c;当目录下的文件发生改变时&#xff0c;实现有修改就发报警邮件 邮件使用QQ邮箱&#xff0c;需要开启smtp&#xff0c;使用手机发生短信&#xff0c;腾讯会给你发邮箱密码。如下所示&#xff1a…

Oracle RAC

环境如下&#xff1a; Linux操作系统&#xff1a;Centos 6.5 64bit &#xff08;这个版本的redhat 6内核等OS在安装grid最后执行root.sh时会出现crs-4124&#xff0c;是oracle11.2.0.1的bug&#xff09; VMware version&#xff1a;Workstation 8.0.3 build-703057 Oracle…

Activiti多人会签例子

Activiti中提供了多实例任务&#xff08;for-each&#xff09;将多实例应到到UserTask中可以实现会签功能。 Multi-instance (for each) Description A multi-instance activity is a way of defining repetition for a certain step in a business process. In programming …

MySQL-ProxySQL中间件(一)| ProxySQL基本概念

目录 MySQL-ProxySQL中间件&#xff08;一&#xff09;| ProxySQL基本概念&#xff1a; https://www.cnblogs.com/SQLServer2012/p/10972593.htmlMySQL-ProxySQL中间件&#xff08;二&#xff09;| Admin Schemas介绍&#xff1a;https://www.cnblogs.com/SQLServer2012/p/109…

标签td设置隐藏(hidden)

这样设置这个td就不会被其他的td给挤掉了! 还有一种方法就是把tr标签的solid设置为0px 这个方法把td标签的left,right,bottom,top的边框的solid全部设置为0px;转载于:https://www.cnblogs.com/tranquilityMan/p/10972811.html

Windows Server 2008 NFS

打开Windows Server 2008的Dos运行窗口&#xff08;不是powershell&#xff09;&#xff0c;然后键入&#xff1a; servermanagercmd.exe -install FS-NFS-Services 安装完毕之后&#xff0c;就要把NFS的存贮映射到Windows Server 2008上某个盘符以供使用&#xff0c;但为了…

金融反欺诈模型----项目实战--机器学习

机器学习&#xff1a;从源数据清洗到特征工程建立谈金融反欺诈模型训练 本文旨在通过一个完整的实战例子&#xff0c;演示从源数据清洗到特征工程建立&#xff0c;再到模型训练&#xff0c;以及模型验证和评估的一个机器学习的完整流程。由于初识机器学习&#xff0c;会比较多的…

Win7下如何挂载NFS共享目录

NFS是Unix中广泛使用的文件共享协议&#xff0c;在Linux下得到了传承&#xff0c;使用简单&#xff0c;读写性能强大。过去Windows与Linux共享文件夹需要使用Samba&#xff08;CIFS&#xff09;协议&#xff0c;虽然定制性更高&#xff0c;但设置和使用都比较繁琐。Windows 7加…

ECharts 点击非图表区域的点击事件不触发问题

1. 通过 myChart.getZr().on(click, fn) 监听整个图表的点击事件&#xff0c;注册回调 myChart.getZr().on(click, () > {//拿到index即可取出被点击数据的所有信息console.log(clickIndex) }) 2. 在 tooltip 的 formatter 函数中&#xff0c;每次调用都记录下需要的参数&am…

强大的django-debug-toolbar,django项目性能分析工具

强大的django-debug-toolbar,django项目性能分析工具 给大家介绍一个用于django中debug模式下查看网站性能等其他信息的插件django-debug-toolbar 首先安装 pip install django-debug-toolbar 接下来在自己django项目中的settings中添加配置 INSTALLED_APPS [debug_toolbar,]M…

个人作业——软件工程实践总结

一、请回望暑假时的第一次作业&#xff0c;你对于软件工程课程的想象 1&#xff09;对比开篇博客你对课程目标和期待&#xff0c;“希望通过实践锻炼&#xff0c;增强计算机专业的能力和就业竞争力”&#xff0c;对比目前的所学所练所得&#xff0c;在哪些方面达到了你的期待和…

利用jdk自带的运行监控工具JConsole观察分析Java程序的运行 Jtop

利用jdk自带的运行监控工具JConsole观察分析Java程序的运行 原文链接 一、JConsole是什么 从Java 5开始 引入了 JConsole。JConsole 是一个内置 Java 性能分析器&#xff0c;可以从命令行或在 GUI shell 中运行。您可以轻松地使用 JConsole&#xff08;或者&#xff0c;它更高端…

java内存溢出分析工具:jmap使用实战

java内存溢出分析工具&#xff1a;jmap使用实战 在一次解决系统tomcat老是内存撑到头&#xff0c;然后崩溃的问题时&#xff0c;使用到了jmap。 1 使用命令 在环境是linuxjdk1.5以上&#xff0c;这个工具是自带的&#xff0c;路径在JDK_HOME/bin/下 jmap -histo pid>a.log…

JDK内置工具使用

JDK内置工具使用 一、javah命令(C Header and Stub File Generator) 二、jps命令(Java Virtual Machine Process Status Tool) 三、jstack命令(Java Stack Trace) 四、jstat命令(Java Virtual Machine Statistics Monitoring Tool) 五、jmap命令(Java Memory Map) 六、jinfo命令…

Windows10系统下wsappx占用CPU资源过高?wsappx是什么?如何关闭wsappx进程?

在Windows10系统开机的时候&#xff0c;wsappx进程占用的CPU资源非常高&#xff0c;导致电脑运行速度缓慢&#xff0c;那么我们如何关闭wsappx进程&#xff0c;让电脑加快运行速度呢&#xff1f;下面就一起来看一下操作的方法吧。 【现象】 1、先来看一下电脑刚开机的时候&…