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