opencv实现车牌提取
主要实现对整张图片中.将车牌分割出来.
需要进行
- 转换为灰度值
- 阈值分割,去除部分区域
- 连通域分析
- 分割出车牌所在轮廓
#include<opencv2/opencv.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main(int argc,char** argv)
{
Mat image;
image = imread("./demo10/02.jpeg",1); //读取原图像
imshow("原图像",image);
Mat gray;
cvtColor(image,gray,COLOR_BGR2GRAY); //转换为灰度图
threshold(gray,gray,151,0,THRESH_TOZERO); //阈值分割,去除无关的内容,低于下限置0
threshold(gray,gray,255,255,THRESH_TOZERO_INV); //高于上限置0
Mat element = getStructuringElement(MORPH_RECT,Size(3,3)); //形态学滤波 3*3的核
morphologyEx(gray,gray,MORPH_CLOSE,element); //进行闭运算
Mat stats,centroids; //连通域分析结果stats:对应各个轮廓的x,y,width,height和面积,centroids:中心点
Mat labels = Mat::zeros(image.size(),CV_32S); //表示当前像素是第几个轮廓
int num_label = connectedComponentsWithStats(gray, labels, stats, centroids,8,4); //连通域分析,num_label对于连通域个数
for(int i=0;i<num_label;i++) //筛选车牌所在连通域,去除其他区域
{
int area = stats.at<int>(i, CC_STAT_AREA); //当前连通域区域的面积
int width = stats.at<int>(i, CC_STAT_WIDTH); //宽度
int height = stats.at<int>(i,CC_STAT_HEIGHT); //高度
//筛选出车牌所在区域的以外的区域,均不赋予彩色显示,并将其连通域区域的中心点去除
//面积,宽度,高度的数值,根据实际车牌的尺寸,加上相机内参数等数据可获得,应保证范围适中;
//不知各参数的,可通过理由该图进行估计
if((area <6000)|(area >10000)| (width <170)|(width >230) |(height <50) | (height>100))
{
centroids.at<Vec2d>(i, 0) =0; //将车牌以外区域的中心点去除,即取消连通域标记
continue;
}
}
int w = image.cols; //原图像像素的列数
int h = image.rows; //原图像像素的行数
Mat ROI = Mat::ones(image.size(),image.type()); //车牌提取结果值定义为全黑
for (int i = 1; i < num_label; i++) {
Vec2d pt = centroids.at<Vec2d>(i, 0); //各轮廓的中心点
int x = stats.at<int>(i, CC_STAT_LEFT); //各轮廓的左上角x坐标
int y = stats.at<int>(i, CC_STAT_TOP); //各轮廓的左上角y坐标
int width = stats.at<int>(i, CC_STAT_WIDTH); //各轮廓的宽度(x,y)点开始到右下角
int height = stats.at<int>(i, CC_STAT_HEIGHT); //各轮廓的高度(x,y)点开始到右下角
int area = stats.at<int>(i, CC_STAT_AREA); //各轮廓的面积(x,y)点开始到右下角
if(pt[0] != 0) //车牌轮廓的中心点非0
{
cout<<pt<<endl; //打印坐标值
//将车牌区域像素提取到ROI(结果图像)中
//如车牌图像倾斜,可利用椭圆拟合函数,获得图像角度再进行计算后分割
for(int xx = x; xx < x+width; xx++)
for(int yy =y; yy < y+height; yy++)
ROI.at<Vec3b>(yy,xx) = image.at<Vec3b>(yy,xx);
}
}
imshow("车牌提取结果",ROI); //显示结果
waitKey(0);
return 0;
}
- 此为结果程序,具体调试我们需要获取:
- 最佳的阈值范围
- 车牌面积的最大范围
- 车牌宽度,高度的最大范围
- 可通过链接: opencv与c++ 阈值操作显示窗口.
等操作来获取.但范围需尽量大,太过局限的范围并没有什么意义