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