一、算法需求

基于基于纹理特征提取车辆照片中的车牌区域

二、问题分析

在车辆照片中提取车牌区域,需要对图像进行系列变化,移除图像的非车牌区域,使车牌区域在图像中变得显著。目前分析发现,在车辆照片中,车牌区域的特点如下:
1、具有固定的颜色(一般车牌为蓝色、白色、黄色、和绿色)
2、具备特定的字符(车牌号包含汉字、字母、数字)
3、字符具备特定排列规则(车牌号都是水平排列的)
目前不考虑考虑颜色实现算法,对于字符而言其特征就是边缘特征丰富,对于水平排列而言其特征就是形态学算子可以较宽

三、核心思路

1、读取图像为灰度图
2、使用sobel算子提取梯度(sobel算子可以提取水平和垂直梯度)
3、利用横向特征使车牌更加显著
4、利用连通域特性优化车牌区域

四、具体实现

4.1 加载图像为灰度图

代码和执行效果如下所示

Mat  grad_y, abs_grad_y, grad_x, abs_grad_x, close_mat, dil_mat, fs_img;Mat srcImage;
srcImage = imread("C:\\Users\\aaa\\Pictures\\Car\\10.jpg");
resize(srcImage, srcImage, { 600,800 });
cvtColor(srcImage, srcImage, COLOR_BGR2GRAY);
imshow("01.灰度图", srcImage);

4.2 利用垂直方向梯度特征

车牌字符的梯度特征较为明显和密集,故可使用sobel算子提取垂直方向梯度特征。对梯度特征进行二值化和闭运算后可以车牌区域在图像中更加显著。

Sobel(srcImage, grad_x, CV_16S, 1, 0, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x);
imshow("02.Sobel 垂直梯度", abs_grad_x);//图像全局二值化
Mat ezh_img;
threshold(abs_grad_x, ezh_img, 200, 255, THRESH_BINARY);
imshow("03.二值化", ezh_img);cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
morphologyEx(ezh_img, close_mat, MORPH_CLOSE, element);
imshow("04.闭运算 ", close_mat);

应图像过大,故只截取车牌周边区域
sobel提取出的车牌区域如下所示

二值化后效果如下所示

闭运算后效果如下

4.3 利用横向特征

4.3.1 横向膨胀

使用宽远大于高的横向排列算子element1 对上述步骤的二值图进行腐蚀,可使车牌区域形成一个连通域,但由于车牌字符11之间空格区域太多,故对整图进行闭运算

//膨胀
cv::Mat element1 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(21, 5));
morphologyEx(close_mat, dil_mat, MORPH_DILATE, element1);
morphologyEx(dil_mat, dil_mat, MORPH_CLOSE,getStructuringElement(cv::MORPH_RECT, cv::Size(7, 7)));
imshow("05.横向膨胀+闭运算 ", dil_mat);

4.3.2 横向开运算

进行横向膨胀后可以发现车牌由于其横向排列的特性,称为了最宽的连通域。故,对图像进行横向开运算,使横向宽度不够的连通域被移除。

Mat open_mat;
cv::Mat element2 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(71, 5));
morphologyEx(dil_mat, open_mat, MORPH_OPEN, element2);
imshow("06.横向开运算 ", open_mat);

4.4 连通域优化

进行横向特征提取后可以发现,目前车牌区域已经是最大的连通域了,故设计函数提取最大的连通域

Mat max_area = findMaxArea2(open_mat);
imshow("07.最大连通域 ", max_area);

findMaxArea2函数的实现如下所示,利用findContours函数计算出所有的轮廓,然后遍历轮廓使用contourArea找出最大的连通域,最后使用drawContours函数绘制最大的连通域。

Mat findMaxArea2(Mat bin_mat) {Mat borad = Mat::zeros(bin_mat.size(), CV_8UC1);vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(bin_mat, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());int max_aero = 0;int max_i = 0;//遍历所有轮廓,获取最大连通域的面积和下标for (int i = 0; i < contours.size(); i++){int aero = contourArea(contours[i]);//计算轮廓面积if (max_aero < aero) {max_aero = aero;max_i = i;}}drawContours(borad, contours, max_i, Scalar(255, 255, 255), -1, 8, hierarchy);cout << max_i << "  aero:" << max_aero << endl;return borad;
}

4.5 车牌区域提取

上图提取的连通域无法完全覆盖到车牌区域,故对其进行膨胀,然后将膨胀结果与原图相乘得到只有车牌区域的图像(变量:only_car_num )。由于只有车牌区域的图像黑色背景过多,使用boundingRect裁剪出车牌区域。
代码和执行效果如下所示:

Mat max_area_pz;
cv::Mat element3 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(31, 31));
morphologyEx(max_area, max_area_pz, MORPH_DILATE, element3);
imshow("08.最大连通域膨胀 ", max_area_pz);Mat max_area_pz_norm = max_area_pz / 255;
Mat only_car_num = srcImage.mul(max_area_pz_norm);Rect bound=boundingRect(only_car_num);
Mat only_car_num2 = only_car_num(bound);
imshow("only_car_num2", only_car_num2); //轮廓  waitKey(0);

可见目前的车牌区域比4.4步骤中的车牌区域大一些,可覆盖到原图车牌上

最终提取的车牌区域图像如下所示

五、总结分析

5.1 算法适用性分析

上述算法在实现车牌检测中主要利用了两个特征:
1、车牌字符都是竖着------》对应关键点:使用sobel在x方式的算子提取特征(车辆的轮廓主要在水平方式上,在垂直方向上轮廓线较少),通过该操作后车牌区域纹理变得显著。
2、车牌字符都是横向排列-----》对于关键点:横向膨胀(使车牌区域连接到一起,构成全图中最大的连通域),通过该操作后将车牌区域特征定义为最大的连通域。

基于上述实现流程,发现上述算法在应用到一些在垂直方向上轮廓线较多的数据时可能存在问题,这主要是存在后部分车型的车头场景(车辆后面的车牌区域是没有太多的垂直纹理)较为复杂时,可能不行。因为车辆的发动起在前车位置,车牌旁边有散热的孔洞,部分车的散热孔是竖直排列的,所设计算法在应用到这类数据时可能会存在不足,具体如下图所示。在应用到以下数据的7和9时则存在误识别。

5.2 完整代码

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>#include <iostream>
#include <assert.h>
#include <vector>
#include <io.h>
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
using namespace cv;
//找到二值图中最大的连通域,并返回
Mat findMaxArea2(Mat bin_mat) {Mat borad = Mat::zeros(bin_mat.size(), CV_8UC1);vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(bin_mat, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());int max_aero = 0;int max_i = 0;//遍历所有轮廓,获取最大连通域的面积和下标for (int i = 0; i < contours.size(); i++){int aero = contourArea(contours[i]);//计算轮廓面积if (max_aero < aero) {max_aero = aero;max_i = i;}}drawContours(borad, contours, max_i, Scalar(255, 255, 255), -1, 8, hierarchy);cout << max_i << "  aero:" << max_aero << endl;return borad;
}
//使用垂直梯度特征求车牌区域
int main() {Mat  grad_y, abs_grad_y, grad_x, abs_grad_x, close_mat, dil_mat, fs_img;Mat srcImage;srcImage = imread("C:\\Users\\aaa\\Pictures\\Car\\10.jpg");resize(srcImage, srcImage, { 600,800 });cvtColor(srcImage, srcImage, COLOR_BGR2GRAY);imshow("01.灰度图", srcImage);Sobel(srcImage, grad_x, CV_16S, 1, 0, 3, 1, 0, BORDER_DEFAULT);convertScaleAbs(grad_x, abs_grad_x);imshow("02.Sobel 垂直梯度", abs_grad_x);//图像全局二值化Mat ezh_img;threshold(abs_grad_x, ezh_img, 200, 255, THRESH_BINARY);imshow("03.二值化", ezh_img);cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));morphologyEx(ezh_img, close_mat, MORPH_CLOSE, element);imshow("04.闭运算 ", close_mat);//膨胀cv::Mat element1 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(21, 5));morphologyEx(close_mat, dil_mat, MORPH_DILATE, element1);morphologyEx(dil_mat, dil_mat, MORPH_CLOSE,getStructuringElement(cv::MORPH_RECT, cv::Size(7, 7)));imshow("05.横向膨胀+闭运算 ", dil_mat);Mat open_mat;cv::Mat element2 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(71, 5));morphologyEx(dil_mat, open_mat, MORPH_OPEN, element2);imshow("06.横向开运算 ", open_mat);Mat max_area = findMaxArea2(open_mat);imshow("07.最大连通域 ", max_area);Mat max_area_pz;cv::Mat element3 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(31, 31));morphologyEx(max_area, max_area_pz, MORPH_DILATE, element3);imshow("08.最大连通域膨胀 ", max_area_pz);Mat max_area_pz_norm = max_area_pz / 255;Mat only_car_num = srcImage.mul(max_area_pz_norm);Rect bound=boundingRect(only_car_num);Mat only_car_num2 = only_car_num(bound);imshow("only_car_num2", only_car_num2); //轮廓  waitKey(0);return 0;
}

opencv 九 提取车辆照片中的车牌区域(基于纹理特征)相关推荐

  1. 批量跨帧提取人脸视频中的脸部区域帧图像python

    代码实现功能 1.所有人脸视频在一个文件夹中. 2.跨帧提取帧图像. 3.截取帧图像的脸部区域. 3.将截取到的所有脸部图像保存到新文件夹中. 代码语言:python3.6 #这个代码实现了批量跨帧提 ...

  2. Python使用OpenCV+pillow提取AVI视频中关键帧图像

    问题描述:使用OpenCV把AVI视频切分成静态图像,提取视频中的关键帧,保存为0.jpg.1.jpg.2.jpg....... 实现步骤: 1)安装扩展库 2)准备一个AVI视频,这里以微课系列(5 ...

  3. 车牌区域提取(定位)综述及各种算法的优缺点

    车牌区域提取通常也称为车牌区域定位,其目的是从含有车牌的图像中找到车牌区域. 车牌定位的重要性不言而喻,作为车牌识别的第一个步骤,车牌区域的提取成功与否是完成车牌识别的基础也是首要决定因素. 车牌区域 ...

  4. python图像纹理提取_提取图像的颜色、纹理特征(传统算法)

    Python-Image-feature-extraction Python实现提取图像的纹理.颜色特征,包含快速灰度共现矩阵(GLCM).LBP特征.颜色矩.颜色直方图.1044197988/Pyt ...

  5. 利用颜色和形态学两种方法进行车牌区域提取的OpenCV代码

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 2016-7-28日:用MSER算法也实现了车牌 ...

  6. 利用MSER算法提取图像区域(车牌区域)的OpenCV代码~

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 我的博客中前面已经写了两种方法来实现车牌区域的提 ...

  7. mser python车牌识别,基于OPENCV的车辆牌照识别系统研究

    摘要: 在我国汽车工业迅猛发展的今天,汽车保有量的逐年大幅增加,对传统的车辆管理和交通运行方式面临着巨大的压力和挑战.为了解决上述问题,车辆牌照自动识别技术(AVI)应运而生,并发展成为现代智能交通系 ...

  8. 利用OpenCV提取图像中的矩形区域(PPT屏幕等)

    ** 前言 ** 最近参加了大创项目,题目涉及到计算机视觉,学姐发了个修正图像的博客链接,于是打算用这个题目入门OpenCV. 分析问题 照片中的PPT区域总是沿着x,y,z三个轴都有倾斜(如下图), ...

  9. opencv车牌区域提取(VS2019 c++)

    主要实现对整张图片中.将车牌分割出来. 需要进行 转换为灰度值 阈值分割,去除部分区域 连通域分析 分割出车牌所在轮廓 #include<opencv2/opencv.hpp> #incl ...

最新文章

  1. 不想被英文文献烧脑的时候, 如何轻松掌握行业最新进展?
  2. 打造安全的网站服务器
  3. post 返回代码_减少冗长代码,利用DDT轻松分离测试数据
  4. springBoot JunitTest的使用以及如何在junit启动前加载
  5. 纯java生成excel
  6. MongoDB基本命令的使用
  7. vue 子组件更新父组件状态 使用sync
  8. java怎么快速创建监听类_如何创建监听器
  9. 如何去掉 WinCE 4.2 的桌面墙纸
  10. Docker安装与入门
  11. javascript 字符串和json的互转
  12. HCIE理论-IPV6
  13. pytorch torchvision类
  14. 2022年起重机司机(限桥式起重机)报名考试及起重机司机(限桥式起重机)考试资料
  15. 告别2018:人间值得,你更值得!
  16. h标签,b标签,em,i ,u,s标签
  17. python入门--常用的numpy函数:arange()
  18. 03 # 网页元素的属性
  19. 阅文JAVA后端笔试
  20. C++反射机制的实现

热门文章

  1. 企业内部服务器主机加固的必要性
  2. 中国金融人喝酒图鉴,全新版!
  3. 两万字自动驾驶技术综述,你想知道的这里都有
  4. 程序员的荒谬之前还是至理名言?——摘录
  5. String中intern方法的作用
  6. 在Linux桌面条件下打开Terminal的快捷键
  7. 基于OBS如何实现毫秒级超低延时直播
  8. CNN损失函数学习(最全)
  9. Python实例练手项目源码 - 小猪佩奇
  10. CFF Explorer 介绍