📄 imageanalysis.cpp
字号:
#include "stdafx.h"
#include "GlobalApi.h"
#include "Cdib.h"
#include <io.h>
#include <errno.h>
#include <math.h>
#include <direct.h>
/*************************************************************************
*
* 函数名称:
* DIBHOLENUMBER()
*
* 参数:
* CDib * pDib - 指向CDib类的指针
*
* 返回值:
* BOOL - 成功返回True,否则返回False。
*
* 说明:
* 该函数将消去图象中面积小于阈值的小区域
*
*************************************************************************/
BOOL DIBHOLENUMBER(CDib *pDib)
{
// 指向源图像的指针
BYTE * lpSrc;
//图象的宽度和高度
LONG lWidth;
LONG lHeight;
// 图像每行的字节数
LONG lLineBytes;
//得到图象的宽度和高度
CSize SizeDim;
SizeDim = pDib->GetDimensions();
lWidth = SizeDim.cx;
lHeight = SizeDim.cy;
//得到实际的Dib图象存储大小
CSize SizeRealDim;
SizeRealDim = pDib->GetDibSaveDim();
// 计算图像每行的字节数
lLineBytes = SizeRealDim.cx;
//图像数据的指针
LPBYTE lpDIBBits = pDib->m_lpImage;
// 循环变量
int i, j, s, n;
// 空穴的数目以及面积阈值
int nHoleNum, nMinArea;
int nBlackPix, temp;
// 正向和反响传播标志
int nDir1,nDir2;
// 用来存储的一位数组
int *pnBinary;
pnBinary =new int[lHeight*lLineBytes];
// 小区域的阈值面积为20个象素点
nMinArea = 50;
// 将图象二值化
for (j = 0; j < lHeight; j++)
{
for(i = 0; i < lWidth; i++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i;
// 白色象素为背景,存成0
if(*lpSrc > 200)
{
pnBinary[lLineBytes * j + i] = 0;
}
// 黑象素存成-1
else
{
pnBinary[lLineBytes * j + i] = -1;
}
}
}
// 空穴数赋初值
nHoleNum = 1;
do
{
s=0;
// 寻找每个空穴的初始象素值
for (j = 1; j < lHeight - 1; j++)
{
for(i = 1; i < lWidth - 1; i++)
{
// 找到初始象素
if(pnBinary[lLineBytes * j + i] == -1)
{
s = 1;
// 将象素值改成当前的空穴数值
pnBinary[lLineBytes * j + i] = nHoleNum;
// 跳出循环
j = lHeight;
i = lLineBytes;
}
}
}
//没有初始象素,跳出循环
if(s == 0)
break;
else
{
do
{
// 正向和反响传播系数赋初值0
nDir1 = 0;
nDir2 = 0;
// 正向扫描
for (j = 1; j < lHeight-1; j++)
{
for(i = 1; i < lWidth-1; i++)
{
nBlackPix = pnBinary[lLineBytes * j + i];
// 如果象素已经被扫描,或者是背景色,进行下一个循环
if(nBlackPix != -1)
continue;
// 如果上侧或者左侧的象素值已经被扫描,且属于当前的空穴,当前的象素值
// 改成空穴的数值
nBlackPix=pnBinary[lLineBytes * (j-1) + i];
if(nBlackPix == nHoleNum)
{
pnBinary[lLineBytes * j + i] = nHoleNum;
nDir1 = 1;
continue;
}
nBlackPix =pnBinary[lLineBytes * j + i - 1];
if(nBlackPix == nHoleNum)
{
pnBinary[lLineBytes * j + i] = nHoleNum;
nDir1 = 1;
}
}
}
// 正向象素全部被扫描,跳出循环
if(nDir1 == 0)
break;
// 反向扫描
for (j = lHeight-2; j >= 1 ; j--)
{
for(i = lWidth-2; i >= 1 ; i--)
{
nBlackPix = pnBinary[lLineBytes * j + i];
// 如果象素已经被扫描,或者是背景色,进行下一个循环
if(nBlackPix != -1)
continue;
// 如果下侧或者右侧的象素值已经被扫描,且属于当前的空穴,当前的象素值
// 改成空穴的数值
nBlackPix=pnBinary[lLineBytes * (j+1) + i];
if(nBlackPix == nHoleNum)
{
pnBinary[lLineBytes * j + i] = nHoleNum;
nDir2 = 1;
continue;
}
nBlackPix =pnBinary[lLineBytes * j + i + 1];
if(nBlackPix == nHoleNum)
{
pnBinary[lLineBytes * j + i] = nHoleNum;
nDir2 = 1;
}
}
}
if(nDir2 == 0)
break;
}
while(1);
}
// 空穴数增加
nHoleNum++;
}
while(1);
nHoleNum -- ;
// 寻找面积小于阈值的空穴区域
for(n = 1; n <= nHoleNum; n++)
{
s = 0;
for (j = 0; j < lHeight - 1; j++)
{
for(i = 0; i < lWidth - 1; i++)
{
nBlackPix =pnBinary[lLineBytes * j + i];
if(nBlackPix == n)
s++;
// 如果区域面积已经大于阈值,跳出循环
if(s > nMinArea)
break;
}
if(s > nMinArea)
break;
}
// 小于阈值的区域,赋以与背景一样的颜色,进行消去
if(s <= nMinArea)
{
for (j = 0; j < lHeight - 1; j++)
{
for(i = 0; i < lWidth - 1; i++)
{
nBlackPix =pnBinary[lLineBytes * j + i + 1];
if(nBlackPix == n)
{
pnBinary[lLineBytes * j + i + 1] = 0;
}
}
}
}
}
// 存储象素值,输出
for(j = 0; j < lHeight; j++)
{
// 列
for(i = 0; i < lWidth; i++)
{
// 二值图象
temp = pnBinary[j * lLineBytes + i] ;
// 指向位图i行j列象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * j + i;
// 更新源图像
if(temp != 0)
* (lpSrc) = 0;
else
* (lpSrc) = 255;
}
}
delete pnBinary;
return true;
}
/*************************************************************************
*
* 函数名称:
* DIBMOMENT()
*
* 参数:
* CDib * pDib - 指向CDib类的指针
*
* 返回值:
* BOOL - 成功返回True,否则返回False。
*
* 说明:
* 该函数计算图象的力矩。
*
*************************************************************************/
BOOL DIBMOMENT(CDib *pDib)
{
// 指向源图像的指针
BYTE * lpSrc;
//图象的宽度和高度
LONG lWidth;
LONG lHeight;
// 图像每行的字节数
LONG lLineBytes;
//得到图象的宽度和高度
CSize SizeDim;
SizeDim = pDib->GetDimensions();
lWidth = SizeDim.cx;
lHeight = SizeDim.cy;
//得到实际的Dib图象存储大小
CSize SizeRealDim;
SizeRealDim = pDib->GetDibSaveDim();
// 计算图像每行的字节数
lLineBytes = SizeRealDim.cx;
//图像数据的指针
LPBYTE lpDIBBits = pDib->m_lpImage;
// 图象的矩
long nImageMoment;
// 循环变量
int i,j;
int ip,jq;
// 临时变量
double temp;
nImageMoment = 0;
// 计算一阶矩
ip = jq = 1;
// 力矩的计算
for (j = 0; j < lHeight; j++)
{
for(i = 0; i < lWidth; i++)
{
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i;
temp = pow((double)i,ip)*pow(double(j),jq);
temp = temp * (*lpSrc);
nImageMoment = nImageMoment + (int)temp;
}
}
// 将结果进行输出
CString CView;
CView.Format("图象的力矩为:%d",nImageMoment);
MessageBox(NULL,CView, "计算结果" , MB_ICONINFORMATION | MB_OK);
return true;
}
/*************************************************************************
*
* 函数名称:
* DIBBARYCENTERMOMENT()
*
* 参数:
* CDib * pDib - 指向CDib类的指针
*
* 返回值:
* BOOL - 成功返回True,否则返回False。
*
* 说明:
* 该函数计算图象的重心矩。
*
*************************************************************************/
BOOL DIBBARYCENTERMOMENT(CDib *pDib)
{
// 指向源图像的指针
BYTE * lpSrc;
//图象的宽度和高度
LONG lWidth;
LONG lHeight;
// 图像每行的字节数
LONG lLineBytes;
//得到图象的宽度和高度
CSize SizeDim;
SizeDim = pDib->GetDimensions();
lWidth = SizeDim.cx;
lHeight = SizeDim.cy;
//得到实际的Dib图象存储大小
CSize SizeRealDim;
SizeRealDim = pDib->GetDibSaveDim();
// 计算图像每行的字节数
lLineBytes = SizeRealDim.cx;
//图像数据的指针
LPBYTE lpDIBBits = pDib->m_lpImage;
// 图象象素值
int nPixelValue;
// 图象重心矩
long nBarycenterMoment;
// 0次矩m00,x方向的一次矩m01和y方向的一次矩m10
long m00, m10, m01;
// 重心x,y坐标值
int nBarycenterX,nBarycenterY;
// 循环变量
int i,j;
// 临时变量
double temp;
// 赋初值为零
m00 = 0;
m01 = 0;
m10 = 0;
nBarycenterMoment = 0;
// 求0次矩m00,x方向的一次矩m01和y方向的一次矩m10
for (j = 0; j < lHeight; j++)
{
for(i = 0; i < lWidth; i++)
{
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i;
nPixelValue = *lpSrc;
m00 = m00 + nPixelValue;
temp = i * nPixelValue;
m01 = m01 + temp;
temp = j * nPixelValue;
m10 = m10 + temp;
}
}
// 重心x,y坐标值
nBarycenterX = (int)(m01 / m00 + 0.5);
nBarycenterY = (int)(m10 / m00 + 0.5);
// 计算重心矩
for (j = 0; j < lHeight; j++)
{
for(i = 0; i < lWidth; i++)
{
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i;
nPixelValue = *lpSrc;
temp = (i - nBarycenterX) * (j - nBarycenterY);
temp = temp * nPixelValue;
nBarycenterMoment = nBarycenterMoment + (int)temp;
}
}
// 将结果进行输出
CString CView;
CView.Format("图象的重心矩为(%d,%d),重心矩为%d"
,nBarycenterX,nBarycenterY,nBarycenterMoment);
MessageBox(NULL,CView, "计算结果" , MB_ICONINFORMATION | MB_OK);
return true;
}
/*************************************************************************
*
* 函数名称:
* DIBSTREETDIS()
*
* 参数:
* CDib * pDib - 指向CDib类的指针
*
* 返回值:
* BOOL - 成功返回True,否则返回False。
*
* 说明:
* 该函数利用棋盘距离对图象进行变换。
*
*************************************************************************/
BOOL DIBSTREETDIS(CDib *pDib)
{
// 指向源图像的指针
BYTE * lpSrc;
//图象的宽度和高度
LONG lWidth;
LONG lHeight;
// 图像每行的字节数
LONG lLineBytes;
//得到图象的宽度和高度
CSize SizeDim;
SizeDim = pDib->GetDimensions();
lWidth = SizeDim.cx;
lHeight = SizeDim.cy;
//得到实际的Dib图象存储大小
CSize SizeRealDim;
SizeRealDim = pDib->GetDibSaveDim();
// 计算图像每行的字节数
lLineBytes = SizeRealDim.cx;
//图像数据的指针
LPBYTE lpDIBBits = pDib->m_lpImage;
// 循环和临时变量
int i,j;
int temp, s;
// 存储象素值的数组
int *pnBinary, *pnStore;
int nImageValue;
pnBinary = new int[lHeight*lLineBytes];
pnStore = new int[lHeight*lLineBytes];
// 将图象二值化
for (j = 0; j < lHeight; j++)
{
for(i = 0; i < lWidth; i++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i;
// 白色象素为背景,存成0
if(*lpSrc > 200)
{
pnBinary[lLineBytes * j + i] = 0;
pnStore [lLineBytes * j + i] = 0;
}
// 黑象素存成1
else
{
pnBinary[lLineBytes * j + i] = 1;
pnStore [lLineBytes * j + i] = 1;
}
}
}
s = 1;
while(s == 1)
{
s = 0;
// 进行距离的累加
for (j = 1; j < lHeight - 1; j++)
{
for(i = 1; i < lWidth - 1; i++)
{
nImageValue = pnBinary[lLineBytes * j + i];
// 如果是背景,进行下一个循环
if(nImageValue == 0)
continue;
// 如果当前象素值和四周的值一样,象素值增加一
if(nImageValue==pnBinary[lLineBytes * (j-1) + i] && nImageValue==pnBinary[lLineBytes * (j+1) + i])
if(nImageValue==pnBinary[lLineBytes * j + i-1] && nImageValue==pnBinary[lLineBytes * j + i+1])
{
pnStore[lLineBytes * j + i]++;
s=1;
}
}
}
// 在进行下一轮循环前将当前的结果储存
for (j = 0; j < lHeight; j++)
for(i = 1; i < lWidth; i++)
pnBinary[lLineBytes * j + i] = pnStore[lLineBytes * j + i];
}
// 存储象素值,输出
for(j = 0; j < lHeight; j++)
{
// 列
for(i = 0; i < lWidth; i++)
{
// 骨架的象素值
temp = pnStore[j * lLineBytes + i] ;
// 指向位图i行j列象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * j + i;
// 更新源图像
* (lpSrc) = (BYTE)((25 - temp) * 10 + 5);
}
}
delete pnStore;
delete pnBinary;
return true;
}
/*************************************************************************
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -