车牌识别大体上需要经历过Sobel定位、颜色定位、SVM对定位来的候选车牌进行评测,给出评分,最后通过提取HOG特征按照训练模型进入ANN识别。

这一章节介绍 定位相关的逻辑代码,其中定位用到 Sobel定位(边缘检测定位), 颜色定位:对应代码里的CarSobelPlateLocation,CarColorPlateLocation;两者定位后得到一些候选的图片,把这些图片送去SVM进行评测,SVM基于HOG提取边缘信息特征,HOG类同之前处理纹理特征的LBP,项目代码在Clion上开发的。

Sobel定位

CarSobelPlateLocation,通过以下的一些步骤进行降噪:

  • 高斯模糊

  • 灰度化

  • 边缘化

  • 二值化

  • 闭操作

高斯模糊

//预处理 :去噪 让车牌区域更加突出Mat blur;//1、高斯模糊(平滑) (1、为了后续操作 2、降噪 )GaussianBlur(src, blur, Size(5, 5), 0);//imshow("高斯模糊",blur);

灰度化

Mat gray;//2、灰度化 去掉颜色 因为它对于我们这里没用  降噪cvtColor(blur, gray, COLOR_BGR2GRAY);imshow("灰度", gray);

边缘化

Mat sobel_16;//3、 边缘检测 让车牌更加突出  在调用时需要以16位来保存数据 在后续操作 以及显示的时候需要转回8位Sobel(gray, sobel_16, CV_16S, 1, 0);//转为8位Mat sobel;convertScaleAbs(sobel_16, sobel);imshow("Sobel", sobel);

二值化

//4. 二值化 黑白Mat shold;//大律法   最大类间算法threshold(sobel, shold, 0, 255, THRESH_OTSU + THRESH_BINARY);imshow("二值", shold);

闭操作

//5、闭操作// 将相邻的白色区域扩大 连接成一个整体Mat close;Mat element = getStructuringElement(MORPH_RECT, Size(17, 3));morphologyEx(shold, close, MORPH_CLOSE, element);imshow("闭操作", close);

以上的操作是在处理降噪,第六步初步赛选。

第六步:最大面积、最小面积.宽高逼。

//6、查找轮廓//获得初步筛选车牌轮廓================================================================//轮廓检测vector< vector<Point>> contours;//查找轮廓 提取最外层的轮廓  将结果变成点序列放入 集合findContours(close, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);//遍历vector<RotatedRect> vec_sobel_roi;for(vector<Point> point:contours){RotatedRect rotatedRect= minAreaRect(point);//rectangle(src, rotatedRect.boundingRect(), Scalar(255, 0, 255));//进行初步的筛选 把完全不符合的轮廓给排除掉 ( 比如:1x1,5x1000 )if (verifySizes(rotatedRect)) {vec_sobel_roi.push_back(rotatedRect);}}

初步赛选:宽高比 float aspec,把不符合的删除掉(1 * 1的, 5* 1000的等候选矩形)

int CarPlateLocation::verifySizes(RotatedRect rotated_rect) {//容错率float error = 0.75f;//训练时候模型的宽高 136 * 32//获得宽高比float aspect = float(136) / float(32);//最小 最大面积 不符合的丢弃//给个大概就行 随时调整//尽量给大一些没关系, 这还是初步筛选。int min = 20 * aspect * 20;int max = 180 * aspect * 180;//比例浮动 error认为也满足//最小宽、高比float rmin = aspect - aspect * error;//最大的宽高比float rmax = aspect + aspect * error;//矩形的面积float area = rotated_rect.size.height * rotated_rect.size.width;//矩形的比例float r = (float) rotated_rect.size.width / (float) rotated_rect.size.height;if ((area < min || area > max) || (r < rmin || r > rmax))return 0;return 1;
}

把斜的图片转正:仿射变换

//1、矫正前 2、矫正后 3、矩形的大小 4、矩形中心点坐标  5、角度
void CarPlateLocation::rotation(Mat src, Mat &dst, Size rect_size,Point2f center, double angle) {//获得旋转矩阵Mat rot_mat = getRotationMatrix2D(center, angle, 1);//运用仿射变换Mat mat_rotated;//矫正后 大小会不一样,但是对角线肯定能容纳int max = sqrt(pow(src.rows, 2) + pow(src.cols, 2));//仿射变换warpAffine(src, mat_rotated, rot_mat, Size(max, max),CV_INTER_CUBIC);imshow("旋转前", src);imshow("旋转", mat_rotated);//截取 尽量把车牌多余的区域截取掉getRectSubPix(mat_rotated, Size(rect_size.width, rect_size.height), center, dst);imshow("截取", dst);mat_rotated.release();rot_mat.release();

颜色定位

1、HSV颜色模型

色调(H), 饱和度(S), 明度(V);

2、BGR 转成 HSV

cvtColor(src,hsv,COLOR_BGR2HSV);

3、色调H

用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;

4、饱和度S

饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。

5、明度V

明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)

在OpenCV中hsv 数据为8UC则取值分别为 0-180 0-255 0-255 ,即蓝色应该是120

按照上面的表格找到蓝色区域 (100 ~ 124), 然后将HSV中的H、S转为 0, V变为255。其它区域的HSV赋值为0。

//3通道int chanles = hsv.channels();//高int h = hsv.rows;//宽数据长度int w = hsv.cols * 3;//判断数据是否为一行存储的//内存足够的话 mat的数据是一块连续的内存进行存储if (hsv.isContinuous()) {w *= h;h = 1;}for (size_t i = 0; i < h; ++i) {//第i 行的数据 hsv的数据 uchar = java byteuchar *p = hsv.ptr<uchar>(i);for (size_t j = 0; j < w; j += 3) {int h = int(p[j]);int s = int(p[j + 1]);int v = int(p[j + 2]);bool blue = false;//蓝色if (h >= 100 && h <= 124 && s >= 43 && s <= 255 && v >= 46 && v <= 255) {blue = true;}if (blue){p[j] = 0;p[j + 1]=0;p[j + 2]=255;}else {//hsv 模型 h:0 红色 亮度和饱和度都是0 ,也就变成了黑色p[j] = 0;p[j + 1] = 0;p[j + 2] = 0;}}}

得到下面的图:

接下来抽取亮度:

//把亮度数据抽出来//把h、s、v分离出来vector<Mat> hsv_split;split(hsv, hsv_split);

然后跟sobel一样通过二值化、大律法等操作

// 整个图片+经过初步赛选的车牌 + 得到的候选车牌tortuosity(src, vec_sobel_roi, dst);for (Mat s: dst) {imshow("候选", s);waitKey();}

筛选出来一个集合:

把两个结合结合起来,然后通过SVM进行评测, 因为不像人脸检测是没有现成的模型。

vector< Mat > sobel_plates;
//sobel定位
plateLocation->location(src, sobel_plates);//颜色定位
vector< Mat > color_plates;
plateColorLocation->location(src, color_plates);vector<Mat> plates;
//把sobel_plates的内容 全部加入plates向量
plates.insert(plates.end(),sobel_plates.begin(), sobel_plates.end());
plates.insert(plates.end(), color_plates.begin(), color_plates.end());

SVM

简单来说,SVM就是用于区分不同的类型(车牌、非车牌)。SVM的训练数据既有特征又有标签,通过训练,让机器可以自己找到特征和标签之间的联系,在面对只有特征没有标签的数据时,可以判断出标签。属于机器学习中的监督学习。线性可分、线性不可分,不可分的时候用核函数来区分:
核函数:用于将不同类型进行提维

人脸检测用的LBP提取特征,这里采取HOG来提取特征。

SVM load模型, 模型是同样是xml文件

svm = SVM::load(svm_model);
CarPlateRecgnize p("/Users/xiuchengyin/Documents/Tina-NDK/OpencvCarRecgnize/resource/HOG_SVM_DATA2.xml");

HOG特征

局部归一化的梯度方向直方图,是一种对图像局部重叠区域的密集型描述符, 它通过计算局部区域的梯度方向直方图来构成特征。

  • 参数1(检测窗口)的宽- 参数2(块大小)的宽 结果与参数3(块滑动增量)的余数要为0 高也一样;

  • 参数4是胞元大小,参数5是梯度方向;

  • HOGDescriptor hog(Size(128, 64), Size(16, 16), Size(8, 8), Size(8, 8), 3);

初始化HOG变量

//参数1的宽-参数2的宽 结果与参数3的余数为0  高也一样svmHog = new HOGDescriptor(Size(128,64),Size(16,16),Size(8,8),Size(8,8),3);

检测窗口被分为:((128-16)/8+1)*((64-16)/8+1)=105个块(Block);

一个Block有4个胞元(Cell);

一个Cell的Hog描述子向量的长度是9;

统计梯度直方图特征,就是将梯度方向(0-360)划分为x个区间,将图像化为16x16的若干个窗口,每个窗口又划分为x个block,每个block再化为4个cell(8x8)。对每一个cell,算出每一像素点的梯度方向,按梯度方向增加对应bin的值,最终综合N个cell的梯度直方图组成特征。

简单来说,车牌的边缘与内部文字组成的一组信息(在边缘和角点的梯度值是很大的,边缘和角点包含了很多物体的形状信息),HOG就是抽取这些信息组成一个直方图。

HOG : 梯度方向弱化光照的影响,适合捕获轮廓。

LBP : 中心像素的LBP值反映了该像素周围区域的纹理信息。

SVM 依据HOG提取的特征将所给的候选图片进行评分,选取最优的:

string CarPlateRecgnize::plateRecgnize(Mat src) {vector< Mat > sobel_plates;//sobel定位sobelPlateLocation->location(src, sobel_plates);//颜色定位vector< Mat > color_plates;colorPlateLocation->location(src, color_plates);vector< Mat > plates;//把sobel_plates的内容 全部加入plates向量plates.insert(plates.end(),sobel_plates.begin(), sobel_plates.end());plates.insert(plates.end(), color_plates.begin(), color_plates.end());int index = -1;float minScore = FLT_MAX; //float的最大值//使用 svm 进行 评测for (int i = 0;i< plates.size();++i){Mat plate = plates[i];//先灰度化,再二值化,灰度化只剩下一个通道Mat gray;cvtColor(plate, gray,COLOR_BGR2GRAY);//二值化 必须是以单通道进行Mat shold;threshold(gray, shold, 0, 255, THRESH_OTSU + THRESH_BINARY);//提取特征Mat features;getHogFeatures(svmHog, shold, features);//features 进行转化,把数据保存成一行Mat samples = features.reshape(1,1);//转化数据存储格式samples.convertTo(samples, CV_32FC1 );//原始模式// svm: 直接告诉你这个数据是属于什么类型.// RAW_OUTPUT:让svm 给出一个评分
//        char name[100];
//        sprintf(name, "候选车牌%d", i);
//        imshow(name, plate);float score = svm->predict(samples, noArray(), StatModel::Flags::RAW_OUTPUT);printf("评分:%f\n",score);if (score < minScore) {minScore = score;index = i;}gray.release();shold.release();features.release();samples.release();}Mat dst;if (index >= 0) {dst = plates[index].clone();}
//    imshow("车牌", dst);
//    waitKey();
//    释放for (Mat p : plates) {p.release();}return string("123");
}

svm评分如下:

/Users/xiuchengyin/Documents/Tina-NDK/OpencvCarRecgnize/cmake-build-debug/OpencvCarRecgnize
评分:-1.224322
评分:1.255759
评分:1.831937
评分:-0.070820
评分:1.525869
评分:1.117042

测试最终取出来的就是我们的车牌选图了。
原文链接:https://juejin.cn/post/6844903714470232078

深延科技|

深延科技成立于2018年,是深兰科技(DeepBlue)旗下的子公司,以“人工智能赋能企业与行业”为使命,助力合作伙伴降低成本、提升效率并挖掘更多商业机会,进一步开拓市场,服务民生。公司推出四款平台产品——深延智能数据标注平台、深延AI开发平台、深延自动化机器学习平台、深延AI开放平台,涵盖从数据标注及处理,到模型构建,再到行业应用和解决方案的全流程服务,一站式助力企业“AI”化。

纯手码 | 基于OpenCV的车牌识别(Sobel、颜色定位),绝对实用相关推荐

  1. 基于OpenCV的车牌识别(Sobel、颜色定位)

    车牌识别大体上需要经历过Sobel定位.颜色定位.SVM对定位来的候选车牌进行评测,给出评分,最后通过提取HOG特征按照训练模型进入ANN识别. 这一章节介绍 定位相关的逻辑代码,其中定位用到 Sob ...

  2. Python 基于 opencv 的车牌识别系统, 可以准确识别车牌号

    大家好,我是程序员徐师兄,6 年大厂程序员经验,点击关注我 简介 毕业设计基于Opencv的车牌识别系统 车牌搜索识别找出某个车牌号 对比识别车牌系统 车牌数据库认证系统 车牌图文搜索系统 车牌数据库 ...

  3. 基于OpenCV的车牌识别的设计与实现

    随着大数据和互联网技术的快速发展,利用人工智能技术实现车牌信息的自动识别推荐成为研究的热门话题.通过对基于OpenCV的车牌识别系统的网站功能需要进行讨论研究,这种跨平台计算机视觉和机器学习非常适用于 ...

  4. 基于Opencv的车牌识别系统想必大家都会了,那么识别后计费系统会了吗?

    概述 车牌识别脚本我相信大家都见过很多,最多的应该就是基于Opencv来实现的,这个小编也是写过几篇,如果有感兴趣的可以关注小编去查看一下.最近听学弟讲,毕业设计是越来越难了.以前毕设只需要实现车牌识 ...

  5. 基于opencv的车牌识别解析与代码

    Jeremy Lin @HQU 车牌识别太出名了,我也就花几天来了解下这个系统,并结合opencv进行实现.下面是一些介绍: 车辆牌照识别(License Plate Recognition,LPR) ...

  6. 基于OpenCV 的车牌识别

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 车牌识别是一种图像处理技术,用于识别不同车辆.这项技术被广泛用于各 ...

  7. c++opencv汉字分割_基于OpenCV 的车牌识别

    车牌识别是一种图像处理技术,用于识别不同车辆.这项技术被广泛用于各种安全检测中.现在让我一起基于OpenCV编写Python代码来完成这一任务. 车牌识别的相关步骤 1.车牌检测:第一步是从汽车上检测 ...

  8. 实战:基于OpenCV 的车牌识别

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 车牌识别是一种图像处理技术,用于识别不同车辆.这项技术被广泛用于各 ...

  9. 不懂就问!如何基于OpenCV 做车牌识别

    前言 车牌识别是一种图像处理技术,用于识别不同车辆.这项技术被广泛用于各种安全检测中.现在让我一起基于OpenCV编写Python代码来完成这一任务. 车牌识别的相关步骤 1.车牌检测:第一步是从汽车 ...

最新文章

  1. http状态码302,303,307的区别
  2. 第八课.特征工程与CTR预测
  3. angular路由移除#号(跟nginx)
  4. 公众号滑动图代码_脱离模板!教你自己动手制作公众号封面图
  5. Lightgbm with Hyperopt
  6. 12.PDE与PTE
  7. 对AFTER触发器的一些整理
  8. 我的asp.net学习心得
  9. oracle一般人能不能学,Oracle人门学习笔记
  10. MySql通过Limit限制查询的行数
  11. c#求三角形面积周长公式_C#源代码—三角形面积、圆的面积
  12. java List转换为字符串并加入分隔符的一些方法总结
  13. 由先序+后序遍历确定序列是否唯一并输出一个中序序列
  14. visio 2013免费激活
  15. timesten mysql_TimesTen进程种类详解
  16. 助焊剂各成分作用浅析
  17. ssis 链接mysql_SSIS 连接数据
  18. 微信在线客服系统-微信公众平台开发
  19. 墨刀导出html无法使用,墨刀用户必读,能解决你80%的问题(持续更新中)
  20. Java计算每月工作天数

热门文章

  1. AWS攻略——VPC初识
  2. 封禁ip、 解封ip实现源码分享
  3. Ngnix IP封禁以及实现自动封禁IP
  4. 百度数据仓库palo使用总结
  5. Endnote中设置期刊名缩写
  6. 每个人都有自己的梦想,每个人都有自己的目标
  7. CentOS下MySQL服务器重启命令
  8. 基于HyperLPR的车牌识别(二)
  9. c语言水文水资源,2020年首都师范大学水文学及水资源考研真题试卷及试题答案,C语言程序设计考研试题下载...
  10. zynq配置成jtag模式_Zynq-7000 MiZ701 SOC硬件使用手册