02.OpenCV 车牌识别 sobel定位

2024-03-03 14:32

本文主要是介绍02.OpenCV 车牌识别 sobel定位,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

opencv模块介绍

简介

​ OpenCV是一个基于BSD许可开源发行的跨平台计算机视觉库。拥有C++,Python和Java接口,并且支持Windows, Linux, Mac OS, iOS 和 Android系统。实现了图像处理和计算机视觉方面的很多通用算法。

模块功能
Core核心基础模块,定义了被所有其他模块和基本数据结构(包括重要的多维数组Mat)使用的基本函数、底层数据结构和算法函数
Imgproc图像处理模块,包括:滤波、高斯模糊、形态学处理、几何变换、颜色空间转换及直方图计算等
Highgui高层用户交互模块,包括:GUI、图像与视频I\O等
Video视频分析,,运动分析及目标跟踪。
Calib3d3D模块,包括:摄像机标定、立体匹配、3D重建等
Features2d二维特征检测与描述模块,包括:图像特征检测、描述、匹配等
Objdetect目标检测模块,如:人脸检测等
MI机器学习模块,包括:支持向量机、神经网络等
Flann最近邻开源库。包含一系列查找算法,自动选取最快算法的机制。
Imgcodecs图像编解码模块,图像文件的读写操作
Photo图像计算(处理)模块,图像修复及去噪。
Shape形状匹配算法模块。描述形状、比较形状
Stitching图像拼接
Superres超分辨率模块
Videoio视频读写模块,视频文件包括摄像头的输入。
Videostab解决拍摄的视频稳定
Dnn深度神经网络
contrib可以引入额外模块
opencv手册百度网盘:

链接:https://pan.baidu.com/s/15w-bgIWOX8_M5CM2w3VAsQ
提取码:unim

整体流程:

在这里插入图片描述

1.高斯模糊

1、高斯模糊:http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html

目的:对图像去噪,为边缘检测算法做准备。

//1,高斯模糊Mat blur;//ksize: they both must be positive and odd//opencv 只接受奇数半径, 半径越大越模糊GaussianBlur(src, blur, Size(5, 5), 0);imshow("原图", src);//imshow("高斯模糊", blur);

2、灰度化

目的:为边缘检测算法准备灰度化环境。

//2,灰度化Mat gray;cvtColor(blur, gray, COLOR_BGR2GRAY);//imshow("灰度化", gray);

为什么先模糊再灰度化?
如果接收的彩色图片 比灰度化的效果要好。

3、sobel运算(得到图像的一阶水平方向导数)

https://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.html

目的:检测图像中的垂直边缘,便于区分车牌。(Sobel运算只能对灰度图像有效,因此进行sobel运算前必须进行前面的灰度化工作)

//3,Sobel运算Mat sobel_16;//输入图像是8位的, uint8//Sobel函数求导后,导数可能的值会大于255或小于0,Sobel(gray, sobel_16, CV_16S, 1, 0);//imshow("sobel_16", sobel_16);//无法显示//转回8位Mat sobel;convertScaleAbs(sobel_16, sobel);//imshow("sobel", sobel);
4、二值化:(非黑即白)

目的:对图像的每个像素做一个阈值处理。为后续的形态学操作准备。

(灰度图像中,每个像素值是0-255,表示灰暗程度。设定一个阈值t,小于t的设为0,否则设为1)

Mat shold;threshold(sobel, shold, 0, 255, THRESH_OTSU + THRESH_BINARY);
5、形态学操作(闭操作)

目的:将车牌字符连接成一个连通区域,便于取轮廓

形态学操作的对象是二值化图像,腐蚀,膨胀是许多形态学操作的基础。

Mat close;Mat element = getStructuringElement(MORPH_RECT, Size(17, 3));morphologyEx(shold, close, MORPH_CLOSE, element);//imshow("闭操作", close);

腐蚀:

原理:像素x至于模板的中心,根据模版的大小,遍历所有被模板覆盖的其他像素,修改像素x的值为所有像素中最小的值。(对于中心点像素x,模板范围内只要有黑色,就会变成黑色)
在这里插入图片描述在这里插入图片描述

膨胀:

原理:与腐蚀操作相反
在这里插入图片描述

开操作:

原理:先腐蚀,再膨胀

在这里插入图片描述

闭操作:

原理:先膨胀,再腐蚀

在这里插入图片描述

6、求轮廓

目的:将连通域的外围画出来,便于形成外接矩形

	//6,找轮廓vector<vector<Point>> contours;findContours(close, //输入图像contours, //输出轮廓RETR_EXTERNAL, //外轮廓CHAIN_APPROX_NONE	//轮廓上所有像素点);RotatedRect rotatedRect;vector<RotatedRect> vec_sobel_rects;

7、尺寸判断

目的:初步筛选排除不可能是车牌的矩形(中国车牌的一般大小是440mm*140mm,宽高比为3.14)

//7,遍历并判断矩形尺寸for each (vector<Point> points in contours){//最小外接矩形rotatedRect = minAreaRect(points);//带角度的矩形//rectangle(src, rotatedRect.boundingRect(), Scalar(0, 0, 255));//尺寸校验if (verifySizes(rotatedRect)) {vec_sobel_rects.push_back(rotatedRect);}}for each (RotatedRect rect in vec_sobel_rects){//rectangle(src, rect.boundingRect(), Scalar(0, 255, 0));}//imshow("找轮廓", src);

/**
* 尺寸校验(宽高比&面积)
*/
int PlateLocate::verifySizes(RotatedRect rotatedRect)
{//容错率float error = 0.75f;//理想宽高比float aspect = float(136) / float(36);//真实宽高比float realAspect = float(rotatedRect.size.width) / float(rotatedRect.size.height);if (realAspect < 1) realAspect = (float)rotatedRect.size.height / (float)rotatedRect.size.width;//真实面积float area = rotatedRect.size.height * rotatedRect.size.width;//最小 最大面积 不符合的丢弃//给个大概就行 随时调整//尽量给大一些没关系, 这还是初步筛选。int areaMin = 44 * aspect * 14;int areaMax = 440 * aspect * 140;//比例浮动 error认为也满足//最小宽高比float aspectMin = aspect - aspect * error;//最大宽高比float aspectMax = aspect + aspect * error;if ((area < areaMin || area > areaMax) || (realAspect < aspectMin || realAspect > aspectMax))return 0;return 1;
}

8、角度判断

目的:初步筛选排除不可能是车牌的矩形

9、旋转矩形

目的:将偏斜的车牌调整为水平,为后面的车牌判断与字符识别提高成功率

仿射变换

10、调整大小

目的:确保候选车牌导入机器学习模型之前尺寸一致

	// 矩形矫正(角度判断,旋转矩形,调整大小)tortuosity(src, vec_sobel_rects, dst_plates);for each (Mat m in dst_plates){imshow("sobel定位候选车牌", m);waitKey();}
/**
* 矩形矫正
*/
void PlateLocate::tortuosity(Mat src, vector<RotatedRect>& rects, vector<Mat>& dst_plates)
{//循环要处理的矩形for (RotatedRect roi_rect : rects) {//矩形角度float roi_angle = roi_rect.angle;float r = (float)roi_rect.size.width / (float)roi_rect.size.height;if (r < 1) {roi_angle = 90 + roi_angle;}//矩形大小Size roi_rect_size = roi_rect.size;//让rect在一个安全的范围(不能超过src)Rect2f  safa_rect;safeRect(src, roi_rect, safa_rect);//候选车牌//抠图  这里不是产生一张新图片 而是在src身上定位到一个Mat 让我们处理//数据和src是同一份Mat src_rect = src(safa_rect);//真正的候选车牌Mat dst;//不需要旋转的 旋转角度小没必要旋转了if (roi_angle - 5 < 0 && roi_angle + 5 > 0) {dst = src_rect.clone();}else {//相对于roi的中心点 不减去左上角坐标是相对于整个图的//减去左上角则是相对于候选车牌的中心点 坐标Point2f roi_ref_center = roi_rect.center - safa_rect.tl();Mat rotated_mat;//矫正 rotated_mat: 矫正后的图片rotation(src_rect, rotated_mat, roi_rect_size, roi_ref_center, roi_angle);dst = rotated_mat;}//调整大小Mat plate_mat;//高+宽plate_mat.create(36, 136, CV_8UC3);resize(dst, plate_mat, plate_mat.size());dst_plates.push_back(plate_mat);dst.release();}
}
/**
* 转换安全矩形
*/
void PlateLocate::safeRect(Mat src, RotatedRect rect, Rect2f& safa_rect)
{//RotatedRect 没有坐标//转为正常的带坐标的边框Rect2f boudRect = rect.boundingRect2f();//左上角 x,yfloat tl_x = boudRect.x > 0 ? boudRect.x : 0;float tl_y = boudRect.y > 0 ? boudRect.y : 0;//这里是拿 坐标 x,y 从0开始的 所以-1//比如宽长度是10,x坐标最大是9, 所以src.clos-1 //右下角float br_x = boudRect.x + boudRect.width < src.cols? boudRect.x + boudRect.width - 1: src.cols - 1;float br_y = boudRect.y + boudRect.height < src.rows? boudRect.y + boudRect.height - 1: src.rows - 1;float  w = br_x - tl_x;float h = br_y - tl_y;if (w <= 0 || h <= 0) return;safa_rect = Rect2f(tl_x, tl_y, w, h);
}
/**
* 旋转
*/
void PlateLocate::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),INTER_CUBIC);//imshow("旋转前", src);//imshow("旋转后", mat_rotated);//截取 尽量把车牌多余的区域截取掉getRectSubPix(mat_rotated, Size(rect_size.width, rect_size.height), center, dst);//imshow("截取后", dst);//waitKey();mat_rotated.release();rot_mat.release();
}

这篇关于02.OpenCV 车牌识别 sobel定位的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/769910

相关文章

opencv图像处理之指纹验证的实现

《opencv图像处理之指纹验证的实现》本文主要介绍了opencv图像处理之指纹验证的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、简介二、具体案例实现1. 图像显示函数2. 指纹验证函数3. 主函数4、运行结果三、总结一、

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

使用PyTorch实现手写数字识别功能

《使用PyTorch实现手写数字识别功能》在人工智能的世界里,计算机视觉是最具魅力的领域之一,通过PyTorch这一强大的深度学习框架,我们将在经典的MNIST数据集上,见证一个神经网络从零开始学会识... 目录当计算机学会“看”数字搭建开发环境MNIST数据集解析1. 认识手写数字数据库2. 数据预处理的

Pytorch微调BERT实现命名实体识别

《Pytorch微调BERT实现命名实体识别》命名实体识别(NER)是自然语言处理(NLP)中的一项关键任务,它涉及识别和分类文本中的关键实体,BERT是一种强大的语言表示模型,在各种NLP任务中显著... 目录环境准备加载预训练BERT模型准备数据集标记与对齐微调 BERT最后总结环境准备在继续之前,确

讯飞webapi语音识别接口调用示例代码(python)

《讯飞webapi语音识别接口调用示例代码(python)》:本文主要介绍如何使用Python3调用讯飞WebAPI语音识别接口,重点解决了在处理语音识别结果时判断是否为最后一帧的问题,通过运行代... 目录前言一、环境二、引入库三、代码实例四、运行结果五、总结前言基于python3 讯飞webAPI语音

使用Python开发一个图像标注与OCR识别工具

《使用Python开发一个图像标注与OCR识别工具》:本文主要介绍一个使用Python开发的工具,允许用户在图像上进行矩形标注,使用OCR对标注区域进行文本识别,并将结果保存为Excel文件,感兴... 目录项目简介1. 图像加载与显示2. 矩形标注3. OCR识别4. 标注的保存与加载5. 裁剪与重置图像

Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)

《Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)》本文介绍了如何使用Python和Selenium结合ddddocr库实现图片验证码的识别和点击功能,感兴趣的朋友一起看... 目录1.获取图片2.目标识别3.背景坐标识别3.1 ddddocr3.2 打码平台4.坐标点击5.图

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

opencv实现像素统计的示例代码

《opencv实现像素统计的示例代码》本文介绍了OpenCV中统计图像像素信息的常用方法和函数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 统计像素值的基本信息2. 统计像素值的直方图3. 统计像素值的总和4. 统计非零像素的数量