?? detect.cpp
字號:
// ************************************************************************
// 文件名:detect.cpp
//
// 圖像分析與檢測API函數庫:
//
// ThresholdDIB() - 圖像閾值分割運算
// AddMinusDIB() - 圖像加減運算
// HprojectDIB() - 圖像水平投影
// VprojectDIB() - 圖像垂直投影
// TemplateDIB() - 圖像模板匹配運算
//
// ************************************************************************
#include "stdafx.h"
#include "detect.h"
#include "DIBAPI.h"
#include <math.h>
#include <direct.h>
/*************************************************************************
*
* 函數名稱:
* ThresholdDIB()
*
* 參數:
* LPSTR lpDIBBits - 指向源DIB圖像指針
* LONG lWidth - 源圖像寬度(象素數)
* LONG lHeight - 源圖像高度(象素數)
*
* 返回值:
* BOOL - 運算成功返回TRUE,否則返回FALSE。
*
* 說明:
* 該函數用于對圖像進行閾值分割運算。
*
************************************************************************/
BOOL WINAPI ThresholdDIB(LPSTR lpDIBBits,LONG lWidth, LONG lHeight)
{
// 指向源圖像的指針
LPSTR lpSrc;
// 指向緩存圖像的指針
LPSTR lpDst;
// 指向緩存DIB圖像的指針
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;
//循環變量
long i;
long j;
//像素值
unsigned char pixel;
//直方圖數組
long lHistogram[256];
//閾值,最大灰度值與最小灰度值,兩個區域的平均灰度值
unsigned char iThreshold,iNewThreshold,iMaxGrayValue,iMinGrayValue,iMean1GrayValue,iMean2GrayValue;
//用于計算區域灰度平均值的中間變量
long lP1,lP2,lS1,lS2;
//迭代次數
int iIterationTimes;
// 圖像每行的字節數
LONG lLineBytes;
// 暫時分配內存,以保存新圖像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if (hNewDIBBits == NULL)
{
// 分配內存失敗
return FALSE;
}
// 鎖定內存
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
// 初始化新分配的內存,設定初始值為255
lpDst = (char *)lpNewDIBBits;
memset(lpDst, (BYTE)255, lWidth * lHeight);
// 計算圖像每行的字節數
lLineBytes = WIDTHBYTES(lWidth * 8);
for (i = 0; i < 256;i++)
{
lHistogram[i]=0;
}
//獲得直方圖
iMaxGrayValue = 0;
iMinGrayValue = 255;
for (i = 0;i < lWidth ;i++)
{
for(j = 0;j < lHeight ;j++)
{
// 指向源圖像倒數第j行,第i個象素的指針
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
pixel = (unsigned char)*lpSrc;
lHistogram[pixel]++;
//修改最大,最小灰度值
if(iMinGrayValue > pixel)
{
iMinGrayValue = pixel;
}
if(iMaxGrayValue < pixel)
{
iMaxGrayValue = pixel;
}
}
}
//迭代求最佳閾值
iNewThreshold = (iMinGrayValue + iMaxGrayValue)/2;
iThreshold = 0;
for(iIterationTimes = 0; iThreshold != iNewThreshold && iIterationTimes < 100;iIterationTimes ++)
{
iThreshold = iNewThreshold;
lP1 =0;
lP2 =0;
lS1 = 0;
lS2 = 0;
//求兩個區域的灰度平均值
for (i = iMinGrayValue;i < iThreshold;i++)
{
lP1 += lHistogram[i]*i;
lS1 += lHistogram[i];
}
iMean1GrayValue = (unsigned char)(lP1 / lS1);
for (i = iThreshold+1;i < iMaxGrayValue;i++)
{
lP2 += lHistogram[i]*i;
lS2 += lHistogram[i];
}
iMean2GrayValue = (unsigned char)(lP2 / lS2);
iNewThreshold = (iMean1GrayValue + iMean2GrayValue)/2;
}
//根據閾值將圖像二值化
for (i = 0;i < lWidth ;i++)
{
for(j = 0;j < lHeight ;j++)
{
// 指向源圖像倒數第j行,第i個象素的指針
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
// 指向目標圖像倒數第j行,第i個象素的指針
lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
pixel = (unsigned char)*lpSrc;
if(pixel <= iThreshold)
{
*lpDst = (unsigned char)0;
}
else
{
*lpDst = (unsigned char)255;
}
}
}
// 復制圖像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 釋放內存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
/*************************************************************************
*
* 函數名稱:
* AddMinusDIB()
*
* 參數:
* LPSTR lpDIBBits - 指向源DIB圖像指針
* LPSTR lpDIBBitsBK - 指向背景DIB圖像指針
* LONG lWidth - 源圖像寬度(象素數)
* LONG lHeight - 源圖像高度(象素數)
* bool bAddMinus - 為true時執行加運算,否則執行減運算。
*
* 返回值:
* BOOL - 運算成功返回TRUE,否則返回FALSE。
*
* 說明:
* 該函數用于對兩幅圖像進行加減運算。
*
* 要求目標圖像為255個灰度值的灰度圖像。
************************************************************************/
BOOL WINAPI AddMinusDIB(LPSTR lpDIBBits, LPSTR lpDIBBitsBK, LONG lWidth, LONG lHeight ,bool bAddMinus)
{
// 指向源圖像的指針
LPSTR lpSrc,lpSrcBK;
// 指向緩存圖像的指針
LPSTR lpDst;
// 指向緩存DIB圖像的指針
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;
//循環變量
long i;
long j;
//像素值
unsigned char pixel,pixelBK;
// 圖像每行的字節數
LONG lLineBytes;
// 暫時分配內存,以保存新圖像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if (hNewDIBBits == NULL)
{
// 分配內存失敗
return FALSE;
}
// 鎖定內存
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
// 初始化新分配的內存,設定初始值為255
lpDst = (char *)lpNewDIBBits;
memset(lpDst, (BYTE)255, lWidth * lHeight);
// 計算圖像每行的字節數
lLineBytes = WIDTHBYTES(lWidth * 8);
for (j = 0;j < lHeight ;j++)
{
for(i = 0;i < lWidth ;i++)
{
// 指向源圖像倒數第j行,第i個象素的指針
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
lpSrcBK = (char *)lpDIBBitsBK + lLineBytes * j + i;
// 指向目標圖像倒數第j行,第i個象素的指針
lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
pixel = (unsigned char)*lpSrc;
pixelBK = (unsigned char)*lpSrcBK;
if(bAddMinus)
*lpDst = pixel + pixelBK > 255 ? 255 : pixel + pixelBK;
else
*lpDst = pixel - pixelBK < 0 ? 0 : pixel - pixelBK;
}
}
// 復制腐蝕后的圖像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 釋放內存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
/*************************************************************************
*
* 函數名稱:
* HprojectDIB()
*
* 參數:
* LPSTR lpDIBBits - 指向源DIB圖像指針
* LONG lWidth - 源圖像寬度(象素數)
* LONG lHeight - 源圖像高度(象素數)
*
* 返回值:
* BOOL - 運算成功返回TRUE,否則返回FALSE。
*
* 說明:
* 該函數用于對兩幅圖像進行水平投影運算。
*
* 要求目標圖像為只有0和255兩個灰度值的灰度圖像。
************************************************************************/
BOOL WINAPI HprojectDIB(LPSTR lpDIBBits,LONG lWidth, LONG lHeight)
{
// 指向源圖像的指針
LPSTR lpSrc;
// 指向緩存圖像的指針
LPSTR lpDst;
// 指向緩存DIB圖像的指針
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;
//循環變量
long i;
long j;
//圖像中每行內的黑點個數
long lBlackNumber;
//像素值
unsigned char pixel;
// 圖像每行的字節數
LONG lLineBytes;
// 暫時分配內存,以保存新圖像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if (hNewDIBBits == NULL)
{
// 分配內存失敗
return FALSE;
}
// 鎖定內存
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
// 初始化新分配的內存,設定初始值為255
lpDst = (char *)lpNewDIBBits;
memset(lpDst, (BYTE)255, lWidth * lHeight);
// 計算圖像每行的字節數
lLineBytes = WIDTHBYTES(lWidth * 8);
for (j = 0;j < lHeight ;j++)
{
lBlackNumber = 0;
for(i = 0;i < lWidth ;i++)
{
// 指向源圖像倒數第j行,第i個象素的指針
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
pixel = (unsigned char)*lpSrc;
if (pixel != 255 && pixel != 0)
{
return false;
}
if(pixel == 0)
{
lBlackNumber++;
}
}
for(i = 0;i < lBlackNumber ;i++)
{
// 指向目標圖像倒數第j行,第i個象素的指針
lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
*lpDst = (unsigned char)0;
}
}
// 復制投影圖像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 釋放內存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
/*************************************************************************
*
* 函數名稱:
* VprojectDIB()
*
* 參數:
* LPSTR lpDIBBits - 指向源DIB圖像指針
* LONG lWidth - 源圖像寬度(象素數)
* LONG lHeight - 源圖像高度(象素數)
*
* 返回值:
* BOOL - 運算成功返回TRUE,否則返回FALSE。
*
* 說明:
* 該函數用于對兩幅圖像進行垂直投影運算。
*
* 要求目標圖像為只有0和255兩個灰度值的灰度圖像。
************************************************************************/
BOOL WINAPI VprojectDIB(LPSTR lpDIBBits,LONG lWidth, LONG lHeight)
{
// 指向源圖像的指針
LPSTR lpSrc;
// 指向緩存圖像的指針
LPSTR lpDst;
// 指向緩存DIB圖像的指針
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;
//循環變量
long i;
long j;
//圖像中每行內的黑點個數
long lBlackNumber;
//像素值
unsigned char pixel;
// 圖像每行的字節數
LONG lLineBytes;
// 暫時分配內存,以保存新圖像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if (hNewDIBBits == NULL)
{
// 分配內存失敗
return FALSE;
}
// 鎖定內存
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
// 初始化新分配的內存,設定初始值為255
lpDst = (char *)lpNewDIBBits;
memset(lpDst, (BYTE)255, lWidth * lHeight);
// 計算圖像每行的字節數
lLineBytes = WIDTHBYTES(lWidth * 8);
for (i = 0;i < lWidth ;i++)
{
lBlackNumber = 0;
for(j = 0;j < lHeight ;j++)
{
// 指向源圖像倒數第j行,第i個象素的指針
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
pixel = (unsigned char)*lpSrc;
if (pixel != 255 && pixel != 0)
{
return false;
}
if(pixel == 0)
{
lBlackNumber++;
}
}
for(j = 0;j < lBlackNumber ;j++)
{
// 指向目標圖像倒數第j行,第i個象素的指針
lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
*lpDst = (unsigned char)0;
}
}
// 復制投影圖像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 釋放內存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
/*************************************************************************
*
* 函數名稱:
* TemplateMatchDIB()
*
* 參數:
* LPSTR lpDIBBits - 指向源DIB圖像指針
* LPSTR lpDIBBitsBK - 指向背景DIB圖像指針
* LONG lWidth - 源圖像寬度(象素數)
* LONG lHeight - 源圖像高度(象素數)
* LONG lTemplateWidth - 模板圖像寬度(象素數)
* LONG lTemplateHeight - 模板圖像高度(象素數)
*
* 返回值:
* BOOL - 運算成功返回TRUE,否則返回FALSE。
*
* 說明:
* 該函數用于對圖像進行模板匹配運算。
*
* 要求目標圖像為255個灰度值的灰度圖像。
************************************************************************/
BOOL WINAPI TemplateMatchDIB (LPSTR lpDIBBits, LPSTR lpTemplateDIBBits, LONG lWidth, LONG lHeight,
LONG lTemplateWidth,LONG lTemplateHeight)
{
// 指向源圖像的指針
LPSTR lpSrc,lpTemplateSrc;
// 指向緩存圖像的指針
LPSTR lpDst;
// 指向緩存DIB圖像的指針
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;
//循環變量
long i;
long j;
long m;
long n;
//中間結果
double dSigmaST;
double dSigmaS;
double dSigmaT;
//相似性測度
double R;
//最大相似性測度
double MaxR;
//最大相似性出現位置
long lMaxWidth;
long lMaxHeight;
//像素值
unsigned char pixel;
unsigned char templatepixel;
// 圖像每行的字節數
LONG lLineBytes,lTemplateLineBytes;
// 暫時分配內存,以保存新圖像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if (hNewDIBBits == NULL)
{
// 分配內存失敗
return FALSE;
}
// 鎖定內存
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
// 初始化新分配的內存,設定初始值為255
lpDst = (char *)lpNewDIBBits;
memset(lpDst, (BYTE)255, lWidth * lHeight);
// 計算圖像每行的字節數
lLineBytes = WIDTHBYTES(lWidth * 8);
lTemplateLineBytes = WIDTHBYTES(lTemplateWidth * 8);
//計算dSigmaT
dSigmaT = 0;
for (n = 0;n < lTemplateHeight ;n++)
{
for(m = 0;m < lTemplateWidth ;m++)
{
// 指向模板圖像倒數第j行,第i個象素的指針
lpTemplateSrc = (char *)lpTemplateDIBBits + lTemplateLineBytes * n + m;
templatepixel = (unsigned char)*lpTemplateSrc;
dSigmaT += (double)templatepixel*templatepixel;
}
}
//找到圖像中最大相似性的出現位置
MaxR = 0.0;
for (j = 0;j < lHeight - lTemplateHeight +1 ;j++)
{
for(i = 0;i < lWidth - lTemplateWidth + 1;i++)
{
dSigmaST = 0;
dSigmaS = 0;
for (n = 0;n < lTemplateHeight ;n++)
{
for(m = 0;m < lTemplateWidth ;m++)
{
// 指向源圖像倒數第j+n行,第i+m個象素的指針
lpSrc = (char *)lpDIBBits + lLineBytes * (j+n) + (i+m);
// 指向模板圖像倒數第n行,第m個象素的指針
lpTemplateSrc = (char *)lpTemplateDIBBits + lTemplateLineBytes * n + m;
pixel = (unsigned char)*lpSrc;
templatepixel = (unsigned char)*lpTemplateSrc;
dSigmaS += (double)pixel*pixel;
dSigmaST += (double)pixel*templatepixel;
}
}
//計算相似性
R = dSigmaST / ( sqrt(dSigmaS)*sqrt(dSigmaT));
//與最大相似性比較
if (R > MaxR)
{
MaxR = R;
lMaxWidth = i;
lMaxHeight = j;
}
}
}
//將最大相似性出現區域部分復制到目標圖像
for (n = 0;n < lTemplateHeight ;n++)
{
for(m = 0;m < lTemplateWidth ;m++)
{
lpTemplateSrc = (char *)lpTemplateDIBBits + lTemplateLineBytes * n + m;
lpDst = (char *)lpNewDIBBits + lLineBytes * (n+lMaxHeight) + (m+lMaxWidth);
*lpDst = *lpTemplateSrc;
}
}
// 復制圖像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 釋放內存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -