开发环境:Qt
车牌定位的大致流程:
- 读取原图
imread();
- 灰度化操作
cvtColor();
或者在读取原图时直接做灰度化处理
- 滤波去噪
blur();
- 梯度运算(sobel算子)
- 阈值化操作(二值化)
threshold();// CV_THRESH_OTSU大律法
- 利用形态学闭运算(先膨胀再腐蚀),闭运算能够排除小型黑洞,将白色区域连成一块。膨胀操作会使物体的边界向外扩张,如果物体内部存在小空洞的话,经过膨胀操作这些洞将被补上,因而不再是边界了。再进行腐蚀操作时,外部边界将变回原来的样子,而这些内部空洞则永远消失了。
- 轮廓检测
//Point->vector->vector>//一个轮廓由几个点构成
vector> contours;//定义存储轮廓的向量
//轮廓又是 点的向量
//CV_RETR_EXTERNAL:只检测外轮廓
//CV_CHAIN_APPROX_SIMPLE 近似方法:只存储垂直/水平/对角直线的起始点-->就是只需要边缘点
findContours(closed,contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
- 绘制轮廓
- 求轮廓的最小外接矩形
- 验证过滤,通过面积和宽高比,验证是否为车牌区域
int i;
// key(整型下标), value(旋转矩形-待选车牌区域)
map imap; //映射/哈希,保存 待选车牌区域
for(i=0; i通过面积和宽高比 验证是否为车牌区域
if(!verify(rect))
continue;
else
imap[i] = rect;//哈希存储,用数组下标的方式-->第几个轮廓以及它的旋转矩形
//https://www.cnblogs.com/fnlingnzb-learner/p/5833051.html
//获取每个矩形的四个顶点
Point2f vertices[4];
rect.points(vertices);
//画直线,看效果
int j;
for(j=0; j<4; j++)
line(closed,vertices[j],vertices[(j+1)%4], Scalar(255), 3);
}
- 利用矩形度来验证
利用迭代器,通过循环找出矩形度和标准车牌最接近的矩形 /*
* 矩形度:周长的平方除以面积
* (2w+2h)*(2w+2h)/w*h
* (4w^2 + 4h^2 + 4w*h)/w*h
* 4w/h + 4h/w + 8
* 4*4.7272 + 4*(1/4.7272) + 4 = 27.75
*/
float min_diff = 10000;//任意初始值
int index = 0;
map::iterator iter;//迭代器
for(iter = imap.begin(); iter!=imap.end(); iter++)//通过循环,找出矩形度与标准车牌的矩形度最接近的
{
//求面积:
int area = contourArea(contours[iter->first]);
int perimeter = arcLength(contours[iter->first],true);
if(area != 0)
{
int squareness = perimeter * perimeter / area;//矩形度
float diff = abs(squareness - 27.75);//差值
if(difffirst;//对应的下标
}
}
}
- 绘制最接近的矩形
- 图像切割
以下为本模块全部代码:
#include "locate.h"
#include
#include
欢迎交流学习,若有不足,还望指正!