?? suanfa1.cpp
字號:
/**************************************************************************
* 文件名:suanfa1.cpp
*
* 車牌定位函數庫:
*
* myMedianFilter() - 圖像中值濾波。
* myGetMedianNum() - 獲取中值。被函數MedianFilter()調用來求中值。
* ReplaceColorPal() - 更換偽彩色編碼表。
* ConvertToGrayScale(); - 24位真彩色圖轉換成灰度圖
* ThresholdTrans(); - 閥值變換
* myTemplate(); - 圖像模板變換,通過改變模板,可以用它實現
* 圖像的平滑、銳化、邊緣識別等操作。
* myHprojectDIB(); - 水平投影
* myVprojectDIB() ; - 垂直投影
* myCropDIB(); - 區域剪裁
*************************************************************************/
#include "stdafx.h"
#include "suanfa1.h"
#include <math.h>
#include <direct.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);
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)
{
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;
}
/*************************************************************************
*
* 函數名稱:
* 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;
}
/*************************************************************************
*
* 函數名稱:
* 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 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-1; i++)
{
// 每列
for(j = 0; j < lWidth-1; 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;
fResult=(*lpSrc)-(*(lpSrc+1));
// 取絕對值
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;
}
/*************************************************************************
*
* 函數名稱:
* 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/5;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;
}
if(findPZ&&iResult[j]<12)
{
pzTop=j;
break;
}
}
pzTop=pzBottom+55;
pzBottom=pzBottom-20; //微量調整
*iBottom=lHeight-pzBottom;
*iTop=lHeight-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/5;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]>10)
{
pzLeft=i;
findPZ=true;
}
pzRight=pzLeft+150;
}
*iLeft=pzLeft-10;
*iRight=pzRight+10;
return true;
}
/*************************************************************************
*
* 函數名稱:
* MedianFilter()
*
* 參數:
* LPSTR lpDIBBits - 指向源DIB圖像指針
* LONG lWidth - 源圖像寬度(象素數)
* LONG lHeight - 源圖像高度(象素數)
* int iFilterH - 濾波器的高度
* int iFilterW - 濾波器的寬度
* int iFilterMX - 濾波器的中心元素X坐標
* int iFilterMY - 濾波器的中心元素Y坐標
*
* 返回值:
* BOOL - 成功返回TRUE,否則返回FALSE。
*
* 說明:
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -