?? 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 + -