车牌识别(1117)

#车牌识别实战


#include <iostream>
#include <opencv2\opencv.hpp>

using namespace std;
using namespace cv;

int main(int, char *argv[])
{
	Mat OriginalImg;

	OriginalImg = imread("carid3.jpg", IMREAD_COLOR);//读取原始彩色图像
	if (OriginalImg.empty())  //判断图像对否读取成功
	{
		cout << "错误!读取图像失败\n";
		return -1;
	}
		imshow("原图", OriginalImg); //显示原始图像
	cout << "Width:" << OriginalImg.rows << "\tHeight:" << OriginalImg.cols << endl;//打印长宽

	Mat ResizeImg;
	if (OriginalImg.cols > 640)
		resize(OriginalImg, ResizeImg, Size(640, 640 * OriginalImg.rows / OriginalImg.cols));
	imshow("尺寸变换图", ResizeImg);

	unsigned char pixelB, pixelG, pixelR;  //记录各通道值
	unsigned char DifMax = 50;             //基于颜色区分的阈值设置
	unsigned char B = 138, G = 63, R = 23; //各通道的阈值设定,针对与蓝色车牌
	Mat BinRGBImg = ResizeImg.clone();  //二值化之后的图像
	int i = 0, j = 0;
	for (i = 0; i < ResizeImg.rows; i++)   //通过颜色分量将图片进行二值化处理
	{
		for (j = 0; j < ResizeImg.cols; j++)
		{
			pixelB = ResizeImg.at<Vec3b>(i, j)[0]; //获取图片各个通道的值
			pixelG = ResizeImg.at<Vec3b>(i, j)[1];
			pixelR = ResizeImg.at<Vec3b>(i, j)[2];

			if (abs(pixelB - B) < DifMax && abs(pixelG - G) < DifMax && abs(pixelR - R) < DifMax)
			{                                           //将各个通道的值和各个通道阈值进行比较
				BinRGBImg.at<Vec3b>(i, j)[0] = 255;     //符合颜色阈值范围内的设置成白色
				BinRGBImg.at<Vec3b>(i, j)[1] = 255;
				BinRGBImg.at<Vec3b>(i, j)[2] = 255;
			}
			else
			{
				BinRGBImg.at<Vec3b>(i, j)[0] = 0;        //不符合颜色阈值范围内的设置为黑色
				BinRGBImg.at<Vec3b>(i, j)[1] = 0;
				BinRGBImg.at<Vec3b>(i, j)[2] = 0;
			}
		}
	}
	imshow("基于颜色信息二值化", BinRGBImg);        //显示二值化处理之后的图像

	Mat BinOriImg;     //形态学处理结果图像
	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); //设置形态学处理窗的大小
	dilate(BinRGBImg, BinOriImg, element);     //进行多次膨胀操作
	dilate(BinOriImg, BinOriImg, element);
	dilate(BinOriImg, BinOriImg, element);

	erode(BinOriImg, BinOriImg, element);      //进行多次腐蚀操作
	erode(BinOriImg, BinOriImg, element);
	erode(BinOriImg, BinOriImg, element);
	imshow("形态学处理后", BinOriImg);        //显示形态学处理之后的图像

	double length, area, rectArea;     //定义轮廓周长、面积、外界矩形面积
	double rectDegree = 0.0;           //矩形度=外界矩形面积/轮廓面积
	double long2Short = 0.0;           //体态比=长边/短边
	CvRect rect;           //外界矩形
	CvBox2D box, boxTemp;  //外接矩形
	CvPoint2D32f pt[4];    //矩形定点变量
	double axisLong = 0.0, axisShort = 0.0;        //矩形的长边和短边
	double axisLongTemp = 0.0, axisShortTemp = 0.0;//矩形的长边和短边
	double LengthTemp;     //中间变量
	float  angle = 0;      //记录车牌的倾斜角度
	float  angleTemp = 0;
	bool   TestPlantFlag = 0;  //车牌检测成功标志位
	cvtColor(BinOriImg, BinOriImg, CV_BGR2GRAY);   //将形态学处理之后的图像转化为灰度图像
	threshold(BinOriImg, BinOriImg, 100, 255, THRESH_BINARY); //灰度图像二值化
	CvMemStorage *storage = cvCreateMemStorage(0);
	CvSeq * seq = 0;     //创建一个序列,CvSeq本身就是一个可以增长的序列,不是固定的序列
	CvSeq * tempSeq = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), storage);
	int cnt = cvFindContours(&(IplImage(BinOriImg)), storage, &seq, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
	//第一个参数是IplImage指针类型,将MAT强制转换为IplImage指针类型
	//返回轮廓的数目 
	//获取二值图像中轮廓的个数
	cout << "number of contours   " << cnt << endl;  //打印轮廓个数
	for (tempSeq = seq; tempSeq != NULL; tempSeq = tempSeq->h_next)
	{
		length = cvArcLength(tempSeq);       //获取轮廓周长
		area = cvContourArea(tempSeq);       //获取轮廓面积
		if (area > 800 && area < 50000)     //矩形区域面积大小判断
		{
			rect = cvBoundingRect(tempSeq, 1);//计算矩形边界
			boxTemp = cvMinAreaRect2(tempSeq, 0);  //获取轮廓的矩形
			cvBoxPoints(boxTemp, pt);              //获取矩形四个顶点坐标
			angleTemp = boxTemp.angle;                 //得到车牌倾斜角度

			axisLongTemp = sqrt(pow(pt[1].x - pt[0].x, 2) + pow(pt[1].y - pt[0].y, 2));  //计算长轴(勾股定理)
			axisShortTemp = sqrt(pow(pt[2].x - pt[1].x, 2) + pow(pt[2].y - pt[1].y, 2)); //计算短轴(勾股定理)

			if (axisShortTemp > axisLongTemp)   //短轴大于长轴,交换数据
			{
				LengthTemp = axisLongTemp;
				axisLongTemp = axisShortTemp;
				axisShortTemp = LengthTemp;
			}
			else
				angleTemp += 90;
			rectArea = axisLongTemp * axisShortTemp;  //计算矩形的面积
			rectDegree = area / rectArea;     //计算矩形度(比值越接近1说明越接近矩形)

			long2Short = axisLongTemp / axisShortTemp; //计算长宽比
			if (long2Short > 2.2 && long2Short < 3.8 && rectDegree > 0.63 && rectDegree < 1.37 && rectArea > 2000 && rectArea < 50000)
			{
				Mat GuiRGBImg = ResizeImg.clone();
				TestPlantFlag = true;             //检测车牌区域成功
				for (int i = 0; i < 4; ++i)       //划线框出车牌区域
					cvLine(&(IplImage(GuiRGBImg)), cvPointFrom32f(pt[i]), cvPointFrom32f(pt[((i + 1) % 4) ? (i + 1) : 0]), CV_RGB(255, 0, 0));
				imshow("提取车牌结果图", GuiRGBImg);    //显示最终结果图

				box = boxTemp;
				angle = angleTemp;
				axisLong = axisLongTemp;
				axisShort = axisShortTemp;
				cout << "倾斜角度:" << angle << endl;
			}
		}
	}

	waitKey();
	return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值