자동차 번호판 문자 절단 (1)
#include
#include //判断一行是不是车牌有效信息的阈值 #define T1 //判断一列是不是车牌有效信息的阈值 #define S(image,x,y) ((uchar*)(image->imageData + image->widthStep*(y)))[(x)] //S(image,x,y)指该图像(x,y)像素点的像素值,[(x)]是数组,类似于a[i] IplImage *pImgSrc; //源图像 IplImage *pImgSrc1 = NULL; //灰度图 IplImage *pImgSrc2 = NULL; //高斯滤波后的图 IplImage *pImgSrc3 = NULL; //边缘检测后的图 IplImage *pImgSrc4 = NULL; //感兴趣的图片 IplImage *pImgSrc5 = NULL; //归一化的灰度图 int i, j; int r_start, r_end; //用来记录车牌开始,结束行 int c_start, c_end; //用来记录车牌开始,结束列 int row[120]; //row[]存放含有有效车牌信息的第j行,把所有有效行放一个数组里面 int col[340]; //存放每个字符双边界(列)的位置 int k = 0; //含有有效车牌信息的行数 int CWidth = 45; //每个字符的宽度(我国的标准车牌有统一的大小,即宽度为45cm,高度为15cm。车牌上单个字符宽45mm) int Space = 12; //字符之间的间隙(第2字符与第3字符之间的间隙为34mm,其他字符间隙为12mm。) int reWidth = 410; //410是感兴趣图像的宽度 int reHeight = 85; //85是感兴趣的高度#include #include using namespace std; #define T 27 void UpAndDown(IplImage *src_son_row);//定义一个子函数,找到图片中含有车牌有效信息的上下边界void LeftAndRight(IplImage *src_son_col); //有效信息的左边界和右边界void find_ROI(IplImage *before_ROI, IplImage *after_ROI);// void cut_and_drawLine(IplImage *befour_cut_image);// , ;
void showChar(IplImage *showChar);//显示所分割出来的字符
void main()
{
pImgSrc = cvLoadImage("004.bmp", -1);
pImgSrc2 = cvCreateImage(cvGetSize(pImgSrc), IPL_DEPTH_8U, 1);//创建一副8位无符型单通道的图片,大小和pImgSrc相同;
pImgSrc1 = cvCreateImage(cvGetSize(pImgSrc), IPL_DEPTH_8U, 1);//同上
pImgSrc3 = cvCreateImage(cvGetSize(pImgSrc), IPL_DEPTH_8U, 1);//同上
cvCvtColor(pImgSrc, pImgSrc1, CV_RGB2GRAY); // 将彩图转化为灰度图,储存在pImgSrc1中;
cvSmooth(pImgSrc1, pImgSrc2, CV_GAUSSIAN, 3, 0, 0); //高斯滤波
cvCanny(pImgSrc2, pImgSrc3, 100, 200, 3); //二值化
cvDilate(pImgSrc3, pImgSrc3, 0, 1);
cvErode(pImgSrc3, pImgSrc3, 0, 1);
cvNamedWindow("cvcanny", 1);
cvShowImage("cvcanny", pImgSrc3);
r_start = 0;
r_end = 0;
c_start = 0;
c_end = 0;
cout << "像素的行数为:" << pImgSrc3->height << endl;
cout << "像素的列数为:" << pImgSrc3->width << endl;
UpAndDown(pImgSrc3); //找到图片中含有车牌有效信息的上边界和下边界
LeftAndRight(pImgSrc3); //找到图片中含有车牌有效信息的最左边界和右边界
find_ROI(pImgSrc2, pImgSrc4); //找到图片中只含有目标区域的部分
pImgSrc5 = cvCreateImage(cvSize(reWidth, reHeight), IPL_DEPTH_8U, 1);
cvResize(pImgSrc4, pImgSrc5, CV_INTER_LINEAR); //线性插值
cvNamedWindow("感兴趣图像的宽度与高度", 1);
cvShowImage("感兴趣图像的宽度与高度", pImgSrc5);
cut_and_drawLine(pImgSrc5); //对含有车牌有效信息的图片分割出字符,并画出分割线
showChar(pImgSrc5); //显示出所有分割出来的字符
cvReleaseImage(&pImgSrc5);
}
void UpAndDown(IplImage *src_son_row) {
//判断每行是不是含有车牌信息的行是通过查看黑点白点变化的次数来确定的
for (j = 0; j < src_son_row->height; j++)
//遍历整幅图的行和列,寻找包含车牌信息的行数
{
int count = 0; // count/2 记录每行白点(水平的白线看做一个点)的个数
for (i = 0; i < src_son_row->width; i++)
{
if (S(src_son_row, i, j) != S(src_son_row, i + 1, j)) //统计行跳数
count++;
if (count > T) //把含有车牌有效信息的行j存放到row[k]
{
row[k] = j;
k++; //记录含有有效车牌信息的行数
break;
}
}
}
cout << "有效行k值为:" << k << endl;
for (i = 0; i//从上边开始,3行连续时认为是起始行
{
if ((row[i] == row[i + 1] - 1) && (row[i + 1] == row[i + 2] - 1)) {
r_start = row[i];
// cout<break;
}
}
cout << "the start row:" << r_start << endl;
cvLine(pImgSrc1, cvPoint(0, r_start), cvPoint(pImgSrc->width, r_start), cvScalar(255, 0, 0), 1, 8, 0);
cvNamedWindow("上画线", 1);
cvShowImage("上画线", pImgSrc1);
for (i = k - 1; i > r_start; i--) //从下边开始,3行连续时认为是起始行
{
if ((row[i] == row[i - 1] + 1) && (row[i - 1] == row[i - 2] + 1)) {
r_end = row[i];
break;
}
}
cout << "the end row:" << r_end << endl;
cvLine(pImgSrc1, cvPoint(0, r_end), cvPoint(pImgSrc->width, r_end), cvScalar(255, 0, 0), 1, 8, 0);
cvNamedWindow("上下画线", 1);
cvShowImage("上下画线", pImgSrc1);
}
void LeftAndRight(IplImage *src_son_col) {
//判断每列是不是含有车牌有效信息是查看每列中含有白点像素的个数
bool flag = false;
for (i = 5; iwidth; i++) //找到左列开始,i的大小可以根据运行效果来更改
{
int count = 0;
for (j = r_start; j{ //找到右列开始
if (S(src_son_col, i, j) == 255)
count++;
if (count>T1)
{
c_start = i;
flag = true;
break;
}
}
if (flag) break;
}
cout << "the start col:" << c_start << endl;
cvLine(pImgSrc1, cvPoint(c_start, r_start), cvPoint(c_start, r_end), cvScalar(255, 0, 0), 1, 8, 0);
cvNamedWindow("左画线", 1);
cvShowImage("左画线", pImgSrc1);
flag = false;
for (i = src_son_col->width - 10; i>c_start; i--)
{
int count = 0;
for (j = r_start; j{ //获得图片感兴趣区域
if (S(src_son_col, i, j) == 255)
count++;
if (count>T1)
{
c_end = i;
flag = true;
break;
}
}
if (flag) break;
}
cout << "the end col:" << c_end << endl;
cvLine(pImgSrc1, cvPoint(c_end, r_start), cvPoint(c_end, r_end), cvScalar(255, 0, 0), 1, 8, 0);
cvNamedWindow("左右画线", 1);
cvShowImage("左右画线", pImgSrc1);
}
void find_ROI(IplImage *before_ROI, IplImage *after_ROI) {
CvRect ROI_rect;
ROI_rect.x = c_start;//用来记录车牌开始的列
ROI_rect.y = r_start;//用来记录车牌开始的行
ROI_rect.width = c_end - c_start;
ROI_rect.height = r_end - r_start;
//设置ROI区域
cvSetImageROI(pImgSrc1, ROI_rect);
pImgSrc4 = cvCreateImage(cvSize(ROI_rect.width, ROI_rect.height), IPL_DEPTH_8U, 1);
cvCopy(pImgSrc1, pImgSrc4);//ROI区域拷贝
cvResetImageROI(pImgSrc1);//释放ROI区域
}
void cut_and_drawLine(IplImage *befour_cut_image) {
//得到每个字符的双边界
//只看水平方向
for (i = 0; i<7; i++)
{
switch (i) {
case 0: //第一个字符名占45个像素
case 1:
col[i * 2] = i*CWidth + i*Space;
cout << col[i * 2] << endl;
col[i * 2 + 1] = (i + 1)*CWidth + i*Space;
cout << col[i * 2 + 1] << endl;
break; //第二个与第三个字符 之间有个点宽度是34个像素case 2: //2~6 45 case 3: case 4: case 5: case 6: col[i * 2] = i*CWidth + i*Space + 27; cout << col[i * 2] << endl; col[i * 2 + 1] = (i + 1)*CWidth + i*Space + 27; cout << col[i * 2 + 1] << endl; break; } } for (i = 0; i<15; i++) // { cvLine(befour_cut_image, cvPoint(col[i], 0), cvPoint(col[i], reHeight), cvScalar(255, 0, 0), 1, 8, 0); } } void showChar(IplImage *showChar) { cvNamedWindow(" ", 1);// “ ” , cvShowImage(" ", showChar);// “ ” cvWaitKey(0); }
:
, (0,45)(57,102) (141,186) (198,243) (255,300) (312,357) (369,414)
, , , 。
, , , , ( )。
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.