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

相关文章

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

opencv 滚动条

参数介绍:createTrackbar( trackbarname , "hello" , &alpha_slider ,alpha_max ,  on_trackbar )  ;在标签中显示的文字(提示滑动条的用途) TrackbarName创建的滑动条要放置窗体的名字 “hello”滑动条的取值范围从 0 到 alpha_max (最小值只能为 zero).滑动后的值存放在

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

Git 的特点—— Git 学习笔记 02

文章目录 Git 简史Git 的特点直接记录快照,而非差异比较近乎所有操作都是本地执行保证完整性一般只添加数据 参考资料 Git 简史 众所周知,Linux 内核开源项目有着为数众多的参与者。这么多人在世界各地为 Linux 编写代码,那Linux 的代码是如何管理的呢?事实是在 2002 年以前,世界各地的开发者把源代码通过 diff 的方式发给 Linus,然后由 Linus

OpenCV结构分析与形状描述符(11)椭圆拟合函数fitEllipse()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 围绕一组2D点拟合一个椭圆。 该函数计算出一个椭圆,该椭圆在最小二乘意义上最好地拟合一组2D点。它返回一个内切椭圆的旋转矩形。使用了由[90]描述的第一个算法。开发者应该注意,由于数据点靠近包含的 Mat 元素的边界,返回的椭圆/旋转矩形数据

树莓派5_opencv笔记27:Opencv录制视频(无声音)

今日继续学习树莓派5 8G:(Raspberry Pi,简称RPi或RasPi)  本人所用树莓派5 装载的系统与版本如下:  版本可用命令 (lsb_release -a) 查询: Opencv 与 python 版本如下: 今天就水一篇文章,用树莓派摄像头,Opencv录制一段视频保存在指定目录... 文章提供测试代码讲解,整体代码贴出、测试效果图 目录 阶段一:录制一段

Verybot之OpenCV应用三:色标跟踪

下面的这个应用主要完成的是Verybot跟踪色标的功能,识别部分还是居于OpenCV编写,色标跟踪一般需要将图像的颜色模式进行转换,将RGB转换为HSV,因为对HSV格式下的图像进行识别时受光线的影响比较小,但是也有采用RGB模式来进行识别的情况,这种情况一般光线条件比较固定,背景跟识别物在颜色上很容易区分出来。         下面这个程序的流程大致是这样的:

Verybot之OpenCV应用二:霍夫变换查找圆

其实我是想通过这个程序来测试一下,OpenCV在Verybot上跑得怎么样,霍夫变换的原理就不多说了,下面是程序: #include "cv.h"#include "highgui.h"#include "stdio.h"int main(int argc, char** argv){cvNamedWindow("vedio",0);CvCapture* capture;i