主要实现对整张图片中.将车牌分割出来.
需要进行
- 转换为灰度值
- 阈值分割,去除部分区域
- 连通域分析
- 分割出车牌所在轮廓
#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/highgui/highgui_c.h>
#include<vector>
#include<cstdlib>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat image;
image = imread("D://7.jpg"); //读取原图像
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 < 100) | (width > 300) | (height < 20) | (height > 70))
{
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;
}
识别结果为: