PlateLocateMethod.cpp
资源名称:车牌识别.rar [点击查看]
上传用户:sgmlaoniu
上传日期:2013-03-16
资源大小:403k
文件大小:27k
源码类别:
Windows编程
开发平台:
Visual C++
- /**************************************************************************
- * 文件名:PlateLocateMethod.cpp
- *
- * 车牌定位函数库:
- *
- * ConvertToGrayScale(); - 24位真彩色图转换成灰度图
- *************************************************************************/
- #include "stdafx.h"
- #include "PlateLocateMethod.h"
- #include "math.h"
- /*************************************************************************
- *
- * 函数名称:
- * ConvertToGrayScale()
- *
- * 参数:
- * LPSTR lpDIB - 指向源DIB图像指针
- *
- * 返回值:
- * BOOL - 成功返回TRUE,否则返回FALSE。
- *
- * 说明:
- * 该函数将24位真彩色图转换成256级灰度图
- *
- ************************************************************************/
- BOOL WINAPI ConvertToGrayScale(LPSTR lpDIB)
- {
- LPSTR lpDIBBits; //指向DIB的象素的指针
- LPSTR lpNewDIBBits; //指向DIB灰度图图像(新图像)开始处象素的指针
- LONG lLineBytes;
- unsigned char * lpSrc; //指向原图像象素点的指针
- unsigned char * lpdest; //指向目标图像象素点的指针
- unsigned char *ired,*igreen,*iblue;
- long lWidth; //图像宽度和高度
- long lHeight;
- long i,j; //循环变量
- lWidth = ::DIBWidth(lpDIB); //DIB 宽度
- lHeight = ::DIBHeight(lpDIB); //DIB 高度
- RGBQUAD *lpRGBquad;
- lpRGBquad = (RGBQUAD *)&lpDIB[sizeof(BITMAPINFOHEADER)]; //INFOHEADER后为调色板
- if(::DIBNumColors(lpDIB) == 256) //256色位图不作任何处理
- {
- return TRUE;
- }
- if(::DIBNumColors(lpDIB) != 256) //非256色位图将它灰度化
- {
- lLineBytes = WIDTHBYTES(lWidth*8*3);//真彩色一个象素为3个字节
- lpdest= new BYTE[lHeight*lWidth];
- lpDIBBits = (LPSTR)lpDIB + sizeof(BITMAPINFOHEADER);//指向DIB象素
- for(i = 0;i < lHeight; i++)
- for(j = 0;j < lWidth*3; j+=3)//每个象素3个字节
- {
- ired = (unsigned char*)lpDIBBits + lLineBytes * i + j + 2;
- igreen = (unsigned char*)lpDIBBits + lLineBytes * i + j + 1;
- iblue = (unsigned char*)lpDIBBits + lLineBytes * i + j ;
- lpdest[i*lWidth + j/3] = (unsigned char)((*ired)*0.299 + (*igreen)*0.588 + (*iblue)*0.114);
- }
- //需要做三件事情:1、修改INFOHEADER 2、增加调色板 3、修改原图像灰度值
- LPBITMAPINFOHEADER lpBI;
- lpBI = (LPBITMAPINFOHEADER)lpDIB;
- lpBI->biBitCount = 8;
- //设置灰度调色板
- for(i = 0;i < 256;i++)
- {
- lpRGBquad[i].rgbRed = (unsigned char)i;
- lpRGBquad[i].rgbGreen = (unsigned char)i;
- lpRGBquad[i].rgbBlue = (unsigned char)i;
- lpRGBquad[i].rgbReserved = 0;
- }
- lpNewDIBBits= ::FindDIBBits(lpDIB); //找到DIB图像象素起始位置
- lLineBytes=WIDTHBYTES(lWidth * 8);
- //修改灰度值
- for(i = 0;i < lHeight; i++)
- for(j = 0;j < lWidth; j++)
- {
- lpSrc = (unsigned char*)lpNewDIBBits + lLineBytes * i+ j ;
- *lpSrc=lpdest[i*lWidth+j];
- }
- delete lpdest;
- }
- return true;
- }
- /*************************************************************************
- *
- * 函数名称:
- * InteEqualize()
- *
- * 参数:
- * LPSTR lpDIBBits - 指向源DIB图像指针
- * LONG lWidth - 源图像宽度(象素数)
- * LONG lHeight - 源图像高度(象素数)
- *
- * 返回值:
- * BOOL - 成功返回TRUE,否则返回FALSE。
- *
- * 说明:
- * 该函数用来对图像进行直方图均衡。
- *
- ************************************************************************/
- BOOL WINAPI InteEqualize(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
- {
- // 指向源图像的指针
- unsigned char* lpSrc;
- // 临时变量
- LONG lTemp;
- // 循环变量
- LONG i;
- LONG j;
- // 灰度映射表
- BYTE bMap[256];
- // 灰度映射表
- LONG lCount[256];
- // 图像每行的字节数
- LONG lLineBytes;
- // 计算图像每行的字节数
- lLineBytes = WIDTHBYTES(lWidth * 8);
- // 重置计数为0
- for (i = 0; i < 256; i ++)
- {
- // 清零
- lCount[i] = 0;
- }
- // 计算各个灰度值的计数
- for (i = 0; i < lHeight; i ++)
- {
- for (j = 0; j < lWidth; j ++)
- {
- lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;
- // 计数加1
- lCount[*(lpSrc)]++;
- }
- }
- // 计算灰度映射表
- for (i = 0; i < 256; i++)
- {
- // 初始为0
- lTemp = 0;
- for (j = 0; j <= i ; j++)
- {
- lTemp += lCount[j];
- }
- // 计算对应的新灰度值
- bMap[i] = (BYTE) (lTemp * 255 / (lHeight * lWidth));
- }
- // 每行
- for(i = 0; i < lHeight; i++)
- {
- // 每列
- for(j = 0; j < lWidth; j++)
- {
- // 指向DIB第i行,第j个象素的指针
- lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
- // 计算新的灰度值
- *lpSrc = bMap[*lpSrc];
- }
- }
- // 返回
- return TRUE;
- }
- /*************************************************************************
- *
- * 函数名称:
- * RobertDIB()
- *
- * 参数:
- * LPSTR lpDIBBits - 指向源DIB图像指针
- * LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
- * LONG lHeight - 源图像高度(象素数)
- * 返回值:
- * BOOL - 边缘检测成功返回TRUE,否则返回FALSE。
- *
- * 说明:
- * 该函数用Robert边缘检测算子对图像进行边缘检测运算。
- *
- * 要求目标图像为灰度图像。
- ************************************************************************/
- BOOL WINAPI RobertDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
- {
- // 指向源图像的指针
- LPSTR lpSrc;
- // 指向缓存图像的指针
- LPSTR lpDst;
- // 指向缓存DIB图像的指针
- LPSTR lpNewDIBBits;
- HLOCAL hNewDIBBits;
- //循环变量
- long i;
- long j;
- //像素值
- double result;
- unsigned char pixel[4];
- // 暂时分配内存,以保存新图像
- hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
- if (hNewDIBBits == NULL)
- {
- // 分配内存失败
- return FALSE;
- }
- // 锁定内存
- lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
- // 初始化新分配的内存,设定初始值为255
- lpDst = (char *)lpNewDIBBits;
- memset(lpDst, (BYTE)255, lWidth * lHeight);
- //使用水平方向的结构元素进行腐蚀
- for(j = lHeight-1; j > 0; j--)
- {
- for(i = 0;i <lWidth-1; i++)
- {
- //由于使用2×2的模板,为防止越界,所以不处理最下边和最右边的两列像素
- // 指向源图像第j行,第i个象素的指针
- lpSrc = (char *)lpDIBBits + lWidth * j + i;
- // 指向目标图像第j行,第i个象素的指针
- lpDst = (char *)lpNewDIBBits + lWidth * j + i;
- //取得当前指针处2*2区域的像素值,注意要转换为unsigned char型
- pixel[0] = (unsigned char)*lpSrc;
- pixel[1] = (unsigned char)*(lpSrc + 1);
- pixel[2] = (unsigned char)*(lpSrc - lWidth);
- pixel[3] = (unsigned char)*(lpSrc - lWidth + 1);
- //计算目标图像中的当前点
- result = sqrt(( pixel[0] - pixel[3] )*( pixel[0] - pixel[3] ) +
- ( pixel[1] - pixel[2] )*( pixel[1] - pixel[2] ));
- *lpDst = (unsigned char)result;
- }
- }
- // 复制腐蚀后的图像
- memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
- // 释放内存
- LocalUnlock(hNewDIBBits);
- LocalFree(hNewDIBBits);
- // 返回
- return TRUE;
- }
- /*************************************************************************
- *
- * 函数名称:
- * ThresholdTrans()
- *
- * 参数:
- * LPSTR lpDIBBits - 指向源DIB图像指针
- * LONG lWidth - 源图像宽度(象素数)
- * LONG lHeight - 源图像高度(象素数)
- * BYTE bThre - 阈值
- *
- * 返回值:
- * BOOL - 成功返回TRUE,否则返回FALSE。
- *
- * 说明:
- * 该函数用来对图像进行阈值变换。对于灰度值小于阈值的象素直接设置
- * 灰度值为0;灰度值大于阈值的象素直接设置为255。
- *
- ************************************************************************/
- BOOL WINAPI ThresholdTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bThre)
- {
- // 指向源图像的指针
- unsigned char* lpSrc;
- // 循环变量
- LONG i;
- LONG j;
- // 图像每行的字节数
- LONG lLineBytes;
- // 计算图像每行的字节数
- lLineBytes = WIDTHBYTES(lWidth * 8);
- // 每行
- for(i = 0; i < lHeight; i++)
- {
- // 每列
- for(j = 0; j < lWidth; j++)
- {
- // 指向DIB第i行,第j个象素的指针
- lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
- // 判断是否小于阈值
- if ((*lpSrc) < bThre)
- {
- // 直接赋值为0
- *lpSrc = 0;
- }
- else
- {
- // 直接赋值为255
- *lpSrc = 255;
- }
- }
- }
- // 返回
- return TRUE;
- }
- /*************************************************************************
- *
- * 函数名称:
- * myHprojectDIB()
- *
- * 参数:
- * LPSTR lpDIBBits - 指向源DIB图像指针
- * LONG lWidth - 源图像宽度(象素数)
- * LONG lHeight - 源图像高度(象素数)
- * INT* iTop - 车牌上边缘
- * INT* iBottom - 车牌下边缘
- * 返回值:
- * BOOL - 成功返回TRUE,否则返回FALSE。
- *
- * 说明:
- * 该函数用于对含车牌图像进行水平投影运算,求取车牌子图像的上下边缘位置
- *
- ************************************************************************/
- BOOL WINAPI myHprojectDIB(LPSTR lpDIB, LONG lWidth, LONG lHeight,
- int* iTop, int* iBottom)
- {
- LPSTR lpDIBBits; //指向DIB的象素的指针
- LONG lLineBytes; // 图像每行的字节数
- unsigned char * lpSrc; //指向原图像象素点的指针
- unsigned char pixel; //像素值
- int i,j;
- // 计算结果
- INT* iResult;
- INT pzBottom,pzTop;
- bool findPZ=false;
- // 找到DIB图像象素起始位置
- lpDIBBits = ::FindDIBBits(lpDIB);
- // 计算图像每行的字节数
- lLineBytes = WIDTHBYTES(lWidth * 8);
- iResult=new INT[lHeight];
- for(i=0;i<lHeight;i++)
- iResult[i]=0;
- for(j=lHeight/7;j<lHeight*0.8;j++)
- {
- iResult[j]=0;
- for(i=0;i<lWidth;i++)
- {
- lpSrc=(unsigned char*)lpDIBBits+lLineBytes*j+i;
- pixel=(unsigned char)(*lpSrc);
- if(pixel==255)
- {
- iResult[j]++;
- }
- }
- if((!findPZ)&&iResult[j]>12)
- {
- pzBottom=j;
- findPZ=true;
- continue;
- }
- if(findPZ&&iResult[j]<12)
- {
- pzTop=j;
- break;
- }
- }
- if(pzTop - pzBottom < 40)
- {
- pzTop=pzTop+55;
- pzBottom=pzBottom-20; //微量调整
- }
- *iBottom=lHeight-pzBottom;
- //*iBottom=pzBottom;
- *iTop=lHeight-pzTop;
- //*iTop=pzTop;
- return true;
- }
- /*************************************************************************
- *
- * 函数名称:
- * myVprojectDIB()
- *
- * 参数:
- * LPSTR lpDIBBits - 指向源DIB图像指针
- * LONG lWidth - 源图像宽度(象素数)
- * LONG lHeight - 源图像高度(象素数)
- * INT* iLeft - 车牌左边缘
- * INT* iRight - 车牌右边缘
- * 返回值:
- * BOOL - 成功返回TRUE,否则返回FALSE。
- *
- * 说明:
- * 该函数用于对含车牌图像进行垂直投影运算,求取车牌子图像的左右边缘位置
- *
- ************************************************************************/
- BOOL WINAPI myVprojectDIB(LPSTR lpDIB, LONG lWidth, LONG lHeight,
- int* iLeft, int* iRight)
- {
- LPSTR lpDIBBits; //指向DIB的象素的指针
- LONG lLineBytes; // 图像每行的字节数
- unsigned char * lpSrc; //指向原图像象素点的指针
- unsigned char pixel; //像素值
- int i,j;
- // 计算结果
- INT* iResult;
- INT pzLeft,pzRight;
- bool findPZ=false;
- // 找到DIB图像象素起始位置
- lpDIBBits = ::FindDIBBits(lpDIB);
- // 计算图像每行的字节数
- lLineBytes = WIDTHBYTES(lWidth * 8);
- iResult=new INT[lWidth];
- for(i=0;i<lWidth;i++)
- iResult[i]=0;
- for(i=lWidth/7;i<lWidth*0.8;i++)
- {
- iResult[i]=0;
- for(j=0;j<lHeight;j++)
- {
- lpSrc=(unsigned char*)lpDIBBits+lLineBytes*j+i;
- pixel=(unsigned char)(*lpSrc);
- if(pixel==255)
- {
- iResult[i]++;
- }
- }
- if((!findPZ)&&iResult[i]>12)
- {
- pzLeft=i;
- findPZ=true;
- continue;
- }
- pzRight=pzLeft+150;
- }
- *iLeft=pzLeft-10;
- *iRight=pzRight+10;
- return true;
- }
- /*************************************************************************
- *
- * 函数名称:
- * Template()
- *
- * 参数:
- * LPSTR lpDIBBits - 指向源DIB图像指针
- * LONG lWidth - 源图像宽度(象素数)
- * LONG lHeight - 源图像高度(象素数)
- * int iTempH - 模板的高度
- * int iTempW - 模板的宽度
- * int iTempMX - 模板的中心元素X坐标 ( < iTempW - 1)
- * int iTempMY - 模板的中心元素Y坐标 ( < iTempH - 1)
- * FLOAT * fpArray - 指向模板数组的指针
- * FLOAT fCoef - 模板系数
- *
- * 返回值:
- * BOOL - 成功返回TRUE,否则返回FALSE。
- *
- * 说明:
- * 该函数用指定的模板(任意大小)来对图像进行操作,参数iTempH指定模板
- * 的高度,参数iTempW指定模板的宽度,参数iTempMX和iTempMY指定模板的中心
- * 元素坐标,参数fpArray指定模板元素,fCoef指定系数。
- *
- ************************************************************************/
- BOOL WINAPI myTemplate(LPSTR lpDIB)
- {
- // 指向复制图像的指针
- LPSTR lpNewDIBBits;
- HLOCAL hNewDIBBits;
- // 指向要复制区域的指针
- unsigned char* lpDst;
- LPSTR lpDIBBits; //指向DIB的象素的指针
- LONG lLineBytes; // 图像每行的字节数
- unsigned char * lpSrc; //指向原图像象素点的指针
- long lWidth; //图像宽度和高度
- long lHeight;
- // 计算结果
- INT fResult1;
- INT fResult2;
- INT fResult;
- // 找到DIB图像象素起始位置
- lpDIBBits = ::FindDIBBits(lpDIB);
- lWidth = ::DIBWidth(lpDIB); //DIB 宽度
- lHeight = ::DIBHeight(lpDIB); //DIB 高度
- // 计算图像每行的字节数
- lLineBytes = WIDTHBYTES(lWidth * 8);
- // 暂时分配内存,以保存新图像
- hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
- // 判断是否内存分配失败
- if (hNewDIBBits == NULL)
- {
- // 分配内存失败
- return false;
- }
- // 锁定内存
- lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
- // 初始化图像为原始图像
- memcpy(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight);
- long i,j; //循环变量
- //
- //不对边缘进行处理
- for(i = 0; i < lHeight; i++)
- {
- // 每列
- for(j = 0; j < lWidth; j++)
- {
- // 指向新DIB第i行,第j个象素的指针
- lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j;
- // 指向DIB第i行,第j个象素的指针
- lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
- fResult1=abs((*lpSrc)-(*(lpSrc+1)));
- fResult2=abs((*lpSrc)-(*(lpSrc+lWidth)));
- if(fResult1 < fResult2)
- fResult = fResult2;
- else fResult = fResult1;
- // 取绝对值
- if(fResult<0) fResult=-fResult;
- // 判断是否超过255
- if(fResult > 255)
- {
- // 直接赋值为255
- * lpDst = 255;
- }
- else
- {
- // 赋值
- * lpDst = (unsigned char) (fResult + 0.5);
- }
- }
- }
- // 复制变换后的图像
- memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
- // 释放内存
- LocalUnlock(hNewDIBBits);
- LocalFree(hNewDIBBits);
- // 返回
- return TRUE;
- }
- /*************************************************************************
- *
- * 函数名称:
- * myCropDIB()
- *
- * 参数:
- * HDIB hDIB - 指向源DIB图像句柄
- * LPRECT lpRect - 指向要剪裁的矩形区域
- *
- * 返回值:
- * HDIB - 返回裁剪后的矩形区域图像句柄。
- *
- * 说明:
- * 该函数用于对指定图像进行指定区域裁剪操作。
- *
- * 要求目标图像为255个灰度值的灰度图像。
- ************************************************************************/
- HDIB WINAPI myCropDIB(HDIB hDIB, LPRECT lpRect)
- {
- LPBITMAPINFO lpbmi = NULL;
- LPBYTE lpSourceBits, lpTargetBits, lpResult;
- HDC hDC = NULL, hSourceDC, hTargetDC;
- HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap;
- DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize;
- int nWidth, nHeight;
- HDIB hNewDIB;
- DWORD dwSize;
- // Get DIB pointer
- if (! hDIB)
- {
- return NULL;
- }
- LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB);
- if (! lpSrcDIB)
- {
- return NULL;
- }
- // Allocate and fill out a BITMAPINFO struct for the new DIB
- dwTargetHeaderSize = sizeof( BITMAPINFOHEADER ) + PaletteSize((LPSTR)lpSrcDIB);
- lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize );
- memcpy(lpbmi, lpSrcDIB, dwTargetHeaderSize);
- nWidth = RECTWIDTH(lpRect);
- nHeight = RECTHEIGHT(lpRect);
- lpbmi->bmiHeader.biWidth = nWidth;
- lpbmi->bmiHeader.biHeight = nHeight;
- // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em
- hDC = ::GetDC( NULL );
- hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 );
- hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 );
- hSourceDC = CreateCompatibleDC( hDC );
- hTargetDC = CreateCompatibleDC( hDC );
- // Flip the bits on the source DIBSection to match the source DIB
- dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader));
- dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader));
- memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize );
- lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize;
- // Select DIBSections into DCs
- hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap );
- hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap );
- // put old bitmap in new bitmap
- BitBlt(hTargetDC, 0, 0, nWidth, nHeight, hSourceDC, lpRect->left, lpRect->top, SRCCOPY);
- // Clean up and delete the DCs
- SelectObject( hSourceDC, hOldSourceBitmap );
- SelectObject( hTargetDC, hOldTargetBitmap );
- DeleteDC( hSourceDC );
- DeleteDC( hTargetDC );
- ::ReleaseDC( NULL, hDC );
- // Flush the GDI batch, so we can play with the bits
- GdiFlush();
- // Allocate enough memory for the new CF_DIB, and copy bits
- dwSize = dwTargetHeaderSize + dwTargetBitsSize;
- hNewDIB =(HDIB)GlobalAlloc(GHND, dwSize);
- lpResult = (LPBYTE)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize );
- memcpy( lpResult, lpbmi, dwTargetHeaderSize );
- memcpy( FindDIBBits( (LPSTR)lpResult ), lpTargetBits, dwTargetBitsSize );
- // final cleanup
- DeleteObject( hTargetBitmap );
- DeleteObject( hSourceBitmap );
- free( lpbmi );
- GlobalUnlock(hDIB);
- GlobalUnlock(hNewDIB);
- return hNewDIB;
- }
- /*************************************************************************
- *
- * 函数名称:
- * MedianFilter()
- *
- * 参数:
- * LPSTR lpDIBBits - 指向源DIB图像指针
- * LONG lWidth - 源图像宽度(象素数)
- * LONG lHeight - 源图像高度(象素数)
- * int iFilterH - 滤波器的高度
- * int iFilterW - 滤波器的宽度
- * int iFilterMX - 滤波器的中心元素X坐标
- * int iFilterMY - 滤波器的中心元素Y坐标
- *
- * 返回值:
- * BOOL - 成功返回TRUE,否则返回FALSE。
- *
- * 说明:
- * 该函数对DIB图像进行中值滤波。
- *
- ************************************************************************/
- BOOL WINAPI myMedianFilter(LPSTR lpDIBBits, LONG lWidth, LONG lHeight,
- int iFilterH, int iFilterW,
- int iFilterMX, int iFilterMY)
- {
- // 指向源图像的指针
- unsigned char* lpSrc;
- // 指向要复制区域的指针
- unsigned char* lpDst;
- // 指向复制图像的指针
- LPSTR lpNewDIBBits;
- HLOCAL hNewDIBBits;
- // 指向滤波器数组的指针
- unsigned char * aValue;
- HLOCAL hArray;
- // 循环变量
- LONG i;
- LONG j;
- LONG k;
- LONG l;
- // 图像每行的字节数
- LONG lLineBytes;
- // 计算图像每行的字节数
- lLineBytes = WIDTHBYTES(lWidth * 8);
- // 暂时分配内存,以保存新图像
- hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
- // 判断是否内存分配失败
- if (hNewDIBBits == NULL)
- {
- // 分配内存失败
- return FALSE;
- }
- // 锁定内存
- lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
- // 初始化图像为原始图像
- memcpy(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight);
- // 暂时分配内存,以保存滤波器数组
- hArray = LocalAlloc(LHND, iFilterH * iFilterW);
- // 判断是否内存分配失败
- if (hArray == NULL)
- {
- // 释放内存
- LocalUnlock(hNewDIBBits);
- LocalFree(hNewDIBBits);
- // 分配内存失败
- return FALSE;
- }
- // 锁定内存
- aValue = (unsigned char * )LocalLock(hArray);
- // 开始中值滤波
- // 行(除去边缘几行)
- for(i = iFilterMY; i < lHeight - iFilterH + iFilterMY + 1; i++)
- {
- // 列(除去边缘几列)
- for(j = iFilterMX; j < lWidth - iFilterW + iFilterMX + 1; j++)
- {
- // 指向新DIB第i行,第j个象素的指针
- lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j;
- // 读取滤波器数组
- for (k = 0; k < iFilterH; k++)
- {
- for (l = 0; l < iFilterW; l++)
- {
- // 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素的指针
- lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i + iFilterMY - k) + j - iFilterMX + l;
- // 保存象素值
- aValue[k * iFilterW + l] = *lpSrc;
- }
- }
- // 获取中值
- * lpDst = myGetMedianNum(aValue, iFilterH * iFilterW);
- }
- }
- // 复制变换后的图像
- memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
- // 释放内存
- LocalUnlock(hNewDIBBits);
- LocalFree(hNewDIBBits);
- LocalUnlock(hArray);
- LocalFree(hArray);
- // 返回
- return TRUE;
- }
- /*************************************************************************
- *
- * 函数名称:
- * GetMedianNum()
- *
- * 参数:
- * unsigned char * bpArray - 指向要获取中值的数组指针
- * int iFilterLen - 数组长度
- *
- * 返回值:
- * unsigned char - 返回指定数组的中值。
- *
- * 说明:
- * 该函数用冒泡法对一维数组进行排序,并返回数组元素的中值。
- *
- ************************************************************************/
- unsigned char WINAPI myGetMedianNum(unsigned char * bArray, int iFilterLen)
- {
- // 循环变量
- int i;
- int j;
- // 中间变量
- unsigned char bTemp;
- // 用冒泡法对数组进行排序
- for (j = 0; j < iFilterLen - 1; j ++)
- {
- for (i = 0; i < iFilterLen - j - 1; i ++)
- {
- if (bArray[i] > bArray[i + 1])
- {
- // 互换
- bTemp = bArray[i];
- bArray[i] = bArray[i + 1];
- bArray[i + 1] = bTemp;
- }
- }
- }
- // 计算中值
- if ((iFilterLen & 1) > 0)
- {
- // 数组有奇数个元素,返回中间一个元素
- bTemp = bArray[(iFilterLen + 1) / 2];
- }
- else
- {
- // 数组有偶数个元素,返回中间两个元素平均值
- bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;
- }
- // 返回中值
- return bTemp;
- }
- /***************************************************************************
- ***************************************************************************/
- BOOL WINAPI myFindRightAngle(CDC* pDC,LPSTR lpDIB,int* iLeft,int* iTop,int* iRight,int* iBottom)
- {
- LPSTR lpDIBBits; //指向DIB的象素的指针
- LONG lLineBytes; // 图像每行的字节数
- unsigned char * lpSrc; //指向原图像象素点的指针
- unsigned char pixel = 0; //像素值
- long lWidth; //图像宽度和高度
- long lHeight;
- int i = 0,j = 0;
- int lineRequired = 12;//确定一条直线至少要18个象素
- int lineLimited = 20;//为确定一条直线应该扫描25个象素
- int linePixelCount = 0;//已扫描到的灰度值为255的象素点
- int pixelCount = 0;//扫描象素时的循环变量
- CPen newRedPen(PS_SOLID,2,RGB(255,0,0));
- pDC->SelectObject(newRedPen);
- HGDIOBJ brush=GetStockObject(NULL_BRUSH);
- pDC->SelectObject((HBRUSH)GetStockObject(NULL_BRUSH));
- //INT pzBottom,pzTop,pzLeft,pzRight;
- struct topLeftCorner {
- int pzTop;
- int pzLeft;
- }topLeft[1000];
- struct bottomRightCorner {
- int pzBottom;
- int pzRight;
- }bottomRight[1000];
- int tlCount = 0;//左上角数组的索引
- int brCount = 0;//右下角数组的索引
- bool findTL=false; //是否找到左上角
- bool findBR=false; //是否找到右下角
- // 找到DIB图像象素起始位置
- lpDIBBits = ::FindDIBBits(lpDIB);
- lWidth = ::DIBWidth(lpDIB); //DIB 宽度
- lHeight = ::DIBHeight(lpDIB); //DIB 高度
- // 计算图像每行的字节数
- lLineBytes = WIDTHBYTES(lWidth * 8);
- for(i = 0;i < 100;i++)
- {
- topLeft[i].pzTop = 0;
- topLeft[i].pzLeft = 0;
- }
- for(i = 0;i < 100;i++)
- {
- bottomRight[i].pzBottom = 0;
- bottomRight[i].pzRight = 0;
- }
- //计算左上角的位置,可能有多个,保存在topLeft数组中
- for(i = 30;i < lHeight - 30;i++)//考虑到车牌的大小,在边缘一定范围内可以不考虑
- {
- linePixelCount = 0;
- for(j = 30;j < lWidth - 30 ;j++)
- {
- linePixelCount = 0;
- for(pixelCount = j;pixelCount < (j + lineLimited);pixelCount++)//计算直线
- {
- lpSrc=(unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + pixelCount;
- pixel=(unsigned char)(*lpSrc);
- if(pixel == 255)
- {
- linePixelCount++;
- //pDC->MoveTo(j,i);
- //pDC->LineTo(j,i);
- }
- }
- /*if(linePixelCount >= lineRequired)
- {
- pDC->MoveTo(j,i);
- pDC->LineTo(j,i);
- }*/
- if(linePixelCount >= lineRequired)
- {
- linePixelCount = 0;
- for(pixelCount = i;pixelCount < (i + lineLimited);pixelCount++)
- {
- lpSrc=(unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - pixelCount) + j;
- pixel=(unsigned char)(*lpSrc);
- if(pixel == 255)
- {
- linePixelCount++;
- //pDC->MoveTo(j,i);
- //pDC->LineTo(j,i);
- }
- }
- }
- if(linePixelCount >= lineRequired)
- {
- findTL = true;
- }
- if(findTL)
- {
- findTL = false;
- linePixelCount = 0;
- topLeft[tlCount].pzTop = i;
- topLeft[tlCount].pzLeft = j;
- pDC->MoveTo(j,i);
- pDC->LineTo(j,i);
- tlCount++;
- }
- }
- }
- CPen newGreenPen(PS_SOLID,2,RGB(0,255,0));
- pDC->SelectObject(newGreenPen);
- //计算右下角的位置,可能有多个,保存在bottomRight数组中
- linePixelCount = 0;//重新初始化计数器
- for(i = 10;i < lHeight - 10;i++)//考虑到车牌的大小,在边缘一定范围内可以不考虑
- {
- linePixelCount = 0;
- for(j = 20;j < lWidth - 20;j++)
- {
- linePixelCount = 0;
- for(pixelCount = j;pixelCount < (j + lineLimited);pixelCount++)//计算直线
- {
- lpSrc=(unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + pixelCount;
- pixel=(unsigned char)(*lpSrc);
- if(pixel == 255)
- {
- linePixelCount++;
- }
- }
- if(linePixelCount >= lineRequired)
- {
- linePixelCount = 0;
- for(pixelCount = i;pixelCount > (i - lineLimited);pixelCount--)
- {
- lpSrc=(unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - pixelCount) + lineRequired + j;
- pixel=(unsigned char)(*lpSrc);
- if(pixel == 255)
- {
- linePixelCount++;
- }
- }
- if(linePixelCount >= lineRequired)
- {
- findBR = true;
- }
- }
- if(findBR)
- {
- findBR = false;
- linePixelCount = 0;
- bottomRight[brCount].pzBottom = i;
- bottomRight[brCount].pzRight = j + lineRequired;
- pDC->MoveTo(j + lineRequired,i);
- pDC->LineTo(j + lineRequired,i);
- brCount++;
- }
- }
- }
- //计算车牌的位置
- int plateUpHeight = 50;
- int plateDownHeight = 30;
- int plateUpWidth = 100;
- int plateDownWidth = 80;
- bool plateFind = false;
- for(i = 0;i < tlCount;i++)
- {
- for(j = brCount - 1 ;j >= 0;j--)
- {
- if((bottomRight[j].pzBottom - topLeft[i].pzTop > plateDownHeight) &&
- (bottomRight[j].pzBottom - topLeft[i].pzTop < plateUpHeight) &&
- (bottomRight[j].pzRight - topLeft[i].pzLeft > plateDownWidth) &&
- (bottomRight[j].pzRight - topLeft[i].pzLeft < plateUpWidth) &&
- (double(bottomRight[j].pzRight - topLeft[i].pzLeft) / (bottomRight[j].pzBottom - topLeft[i].pzTop)) > 2)
- {
- *iTop = topLeft[i].pzTop;
- *iLeft = topLeft[i].pzLeft;
- *iBottom = bottomRight[j].pzBottom + 10;
- *iRight = bottomRight[j].pzRight + 15;
- plateFind = true;
- break;
- }
- else
- {
- //i++;
- //j--;
- }
- }
- if(plateFind) break;
- }
- /**iTop = topLeft[0].pzTop;
- *iLeft = topLeft[0].pzLeft;
- *iBottom = bottomRight[0].pzBottom;
- *iRight = bottomRight[0].pzRight;*/
- return true;
- }
- /*************************************************************************
- *在图像上画一个矩形
- *
- *
- *
- *************************************************************************/
- BOOL WINAPI DrawRectangle(CDC* pDC,int iLeft,int iTop,int iRight,int iBottom)
- {
- CPen newPen(PS_SOLID,2,RGB(255,0,0));
- pDC->SelectObject(newPen);
- HGDIOBJ brush=GetStockObject(NULL_BRUSH);
- pDC->SelectObject((HBRUSH)GetStockObject(NULL_BRUSH));
- pDC->Rectangle(iLeft,iTop,iRight,iBottom);
- return true;
- }