#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void getBlueMask(IplImage*src, IplImage*dst);
int main(){
//读入原始图像
IplImage*src_image=cvLoadImage("C:\\Users\\aoe\\Desktop\\chepai-matlab\\chepai3.jpg");
//生成原始图像的一个副本,方便处理
IplImage *Psrc_image = cvCreateImage(cvGetSize(src_image), src_image->depth, src_image->nChannels);
Psrc_image = cvCloneImage(src_image);
//将RGB模型转换成HSV模型
IplImage *hsv = cvCreateImage(cvGetSize(Psrc_image), IPL_DEPTH_8U, 3);
cvCvtColor(Psrc_image, hsv, CV_BGR2HSV);
//将彩色图像转换成灰度图像
IplImage*blue = cvCreateImage(cvGetSize(Psrc_image), IPL_DEPTH_8U, 1);
cvCvtColor(Psrc_image, blue, CV_BGR2GRAY);
//利用车牌蓝底白字对车牌区域进行检索,车色车牌区域保留,非车牌区域置0
getBlueMask(hsv, blue);
cvNamedWindow("blue");
cvShowImage("blue", blue);
//二值化,将车牌区域置为白色
IplImage*bin = cvCreateImage(cvGetSize(Psrc_image), IPL_DEPTH_8U, 1);
cvThreshold(blue, bin, 0, 255, CV_THRESH_BINARY);
cvNamedWindow("bin");
cvShowImage("bin", bin);
//保留一个副本
IplImage*image = cvCreateImage(cvGetSize(Psrc_image), IPL_DEPTH_8U, 1);
cvCopy(bin, image);
cvNamedWindow("image");
cvShowImage("image", image);
//水平投影
int level_shadow[2048];
int height = Psrc_image->height;
int width = Psrc_image->width;
CvScalar s_shadow;
//内存初始化
memset(level_shadow, 0, sizeof(level_shadow));
for (int j = height - 1; j >= 0; j--)
{
for (int i = 0; i < width; i++)
{
s_shadow = cvGet2D(image, j, i);
if (s_shadow.val[0] != 0)
{
level_shadow[j]++;//统计每行不为零的像素个数
}
}
}
//若每一行的像素累加和除以上一行的像素累加和小于一个阈值,则将其像素累加和置0
for (int j = height - 1; j >= 1; j--)
{
if (level_shadow[j - 1] != 0)
{
if ((float(level_shadow[j])) / (float(level_shadow[j - 1])) < 0.6)
level_shadow[j] = 0;
}
}
for (int j = height - 1; j >= 0; j--)
{
if (level_shadow[j] != 0)
level_shadow[j] = level_shadow[j + 1] + 1;//统计水平像素不为0的区间
}
int y_min = 0;
int y_max = 0;
int m_max_value = 0;
m_max_value = level_shadow[0];
for (int j = 0; j < height; j++)
{
if (level_shadow[j]>m_max_value)
{
m_max_value = level_shadow[j];//求取车牌区域最小行和车牌区域最大行及车牌区域的高度
y_min = j;
y_max = y_min + m_max_value;
}
}
if (m_max_value < 10)
cout << "提取车牌高度失败!" << endl;
CvRect ROI_Plate_Height;
ROI_Plate_Height.x = 0;
ROI_Plate_Height.y = y_min;
ROI_Plate_Height.width = Psrc_image->width;
ROI_Plate_Height.height = m_max_value;
cvSetImageROI(image, ROI_Plate_Height);
//裁剪车牌区域
IplImage*pROI_Height_Image = cvCreateImage(cvSize(ROI_Plate_Height.width, ROI_Plate_Height.height),8, 1);
cvCopy(image, pROI_Height_Image);
int copy_m_max_value = m_max_value;
while ((copy_m_max_value % 3) != 0)
{
copy_m_max_value--;
}
int Close_width = int(copy_m_max_value*0.6);
int Close_height = copy_m_max_value;
//闭运算
IplConvKernel*pKernel_Close = cvCreateStructuringElementEx(Close_width, Close_height, Close_width / 2, Close_width / 2, CV_SHAPE_RECT, NULL);
cvMorphologyEx(pROI_Height_Image, pROI_Height_Image, NULL, pKernel_Close, CV_MOP_CLOSE, 1);
cvNamedWindow("pROI_Height_Image");
cvShowImage("pROI_Height_Image", pROI_Height_Image);
int x_min = 0;
int x_max = 0;
int m_row_max_value = 0;
int count_row[2048];
memset(count_row, 0, sizeof(count_row));
//统计车牌的宽度
int mid_height = m_max_value / 2;
uchar*ptr_mid = (uchar*)(pROI_Height_Image->imageData + mid_height*pROI_Height_Image->widthStep);
for (int i = width - 1; i >= 0; i--)
{
if (ptr_mid[i] != 0)
count_row[i] = count_row[i + 1] + 1;
}
int max_value_count_row = count_row[0];
for (int i = 0; i < width; i++)
{
if (count_row[i]>max_value_count_row)
{
max_value_count_row = count_row[i];//求取车牌区域最小列和车牌区域最大列及车牌区域的宽度
x_min = i;
x_max = x_min + max_value_count_row;
}
}
if (float(max_value_count_row) / float(m_max_value)<3 || float(max_value_count_row) / float(m_max_value)>6)
cout << "提取车牌高度失败!" << endl;
CvRect ROI_Plate;
ROI_Plate.x = x_min;
ROI_Plate.y = y_min;
ROI_Plate.width = max_value_count_row;
ROI_Plate.height = m_max_value;
if (ROI_Plate.x<0 || ROI_Plate.x>width)
cout << "提取车牌高度失败!" << endl;
if (ROI_Plate.y<0 || ROI_Plate.y>height)
cout << "提取车牌高度失败!" << endl;
if ((ROI_Plate.x + ROI_Plate.width)>width)
cout << "提取车牌高度失败!" << endl;
if ((ROI_Plate.y + ROI_Plate.height)>height)
cout << "提取车牌高度失败!" << endl;
cvSetImageROI(bin, ROI_Plate);
IplImage*plate_image = cvCreateImage(cvSize(ROI_Plate.width, ROI_Plate.height), 8, 1);
cvCopy(bin, plate_image);
cvNot(plate_image, plate_image);
cvNamedWindow("plate_image");
cvShowImage("plate_image", plate_image);
cvWaitKey();
}
void getBlueMask(IplImage*src, IplImage*dst)
{
int h, s, v;
int hi = 120, lo = 100;
int lo_sat_v = 110;
for (int i = 0; i < src->height; i++)
{
uchar*ptr = (uchar*)(src->imageData + i*src->widthStep);
uchar*ptr2 = (uchar*)(dst->imageData + i*dst->widthStep);
for (int j = 0; j < src->width; j++)
{
h = ptr[3*j + 0];
s = ptr[3*j + 1];
v = ptr[3*j + 2];
if ((s < lo_sat_v || v<lo_sat_v) || (h>hi || h < lo))
{
ptr2[j] = 0;
}
}
}
}
车牌区域定位——opencv
最新推荐文章于 2023-06-26 16:11:37 发布