📄 splitproc.cpp
字号:
}
}
v_r /= 9;
v_g /= 9;
v_b /= 9;
if (v_r < 0)
v_r = 0;
if (v_g < 0)
v_g = 0;
if (v_b < 0)
v_b = 0;
m_temp[j * lLineBytes + i * 3] = v_r;
m_temp[j * lLineBytes + i * 3 + 1] = v_g;
m_temp[j * lLineBytes + i * 3 + 2] = v_b;
}
}
// 回存处理结果到DIB
memcpy(lpNewDIBBits1, m_temp, lLineBytes * lHeight);
// 第一图象缓存同第二~第八图象缓存数据依次比较,将
// 大值保存在第一图象缓存。
for (int loop = 1; loop < 8; loop++)
{
// 复制图象数据到中间缓存
memcpy(m_temp, lpNewDIBBits2, lLineBytes * lHeight);
// 3X3 模版
for (i = 0; i < lWidth; i++) //被处理像素在i列
{
for (j = 0; j < lHeight; j++) //被处理像素在j行
{
v_r = v_g = v_b = p_g = 0;
for (k = i - 1; k < i + 2; k++) //3*3模版
{
for (l = j - 1; l < j + 2; l++)
{
// 防止内存溢出
if (k >= 0 && l >= 0 && k < lWidth && l < lHeight)
{
v_r += *(lpNewDIBBits2 + l * lLineBytes + k * 3) * g[loop][p_g];
v_g += *(lpNewDIBBits2 + l * lLineBytes + k * 3 + 1) * g[loop][p_g];
v_b += *(lpNewDIBBits2 + l * lLineBytes + k * 3 + 2) * g[loop][p_g];
p_g++;
}
}
}
v_r /= 9;
v_g /= 9;
v_b /= 9;
if (v_r < 0)
v_r = 0;
if (v_g < 0)
v_g = 0;
if (v_b < 0)
v_b = 0;
m_temp[j * lLineBytes + i * 3] = v_r;
m_temp[j * lLineBytes + i * 3 + 1] = v_g;
m_temp[j * lLineBytes + i * 3 + 2] = v_b;
}
}
// 回存处理结果到DIB
memcpy(lpNewDIBBits2, m_temp, lLineBytes * lHeight);
// 提取两缓存对应象素的最大值
for (j = 0; j < lHeight; j++)
{
for (i = 0; i < lLineBytes; i++)
{
lpDst1 = (LPBYTE)lpNewDIBBits1 + lLineBytes * j + i;
lpDst2 = (LPBYTE)lpNewDIBBits2 + lLineBytes * j + i;
if (*lpDst2 > *lpDst1)
*lpDst1 = * lpDst2;
}
}
}
// 将检测结果复制到原图象
memcpy(lpDIBBits, lpNewDIBBits1, lLineBytes * lHeight);
// 释放内存、解除锁定
LocalUnlock(hNewDIBBits1);
LocalFree(hNewDIBBits1);
LocalUnlock(hNewDIBBits2);
LocalFree(hNewDIBBits2);
::GlobalUnlock((HGLOBAL) hDIB);
delete[] m_temp;
// 恢复光标
EndWaitCursor();
}
/*************************************************************************
*
* 函数名称:
* ContourDIB()
*
* 参数:
* HDIB hDIB - 待处理的DIB
* COLORREF clrSeed_I - 种子点一的RGB值
* COLORREF clrSeed_II- 种子点二的RGB值
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数对图象进行轮廓提取
*
************************************************************************/
void CSplitProc::ContourDIB(HDIB hDIB,COLORREF clrSeed_I,COLORREF clrSeed_II)
{
// 循环变量
LONG i;
LONG j;
LONG k;
LONG l;
// 指向DIB的指针
LPBYTE lpDIB;
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 计算种子点一的灰度值
unsigned char R_I = GetRValue(clrSeed_I);
unsigned char G_I = GetGValue(clrSeed_I);
unsigned char B_I = GetBValue(clrSeed_I);
// 计算种子点二的灰度值
unsigned char R_II = GetRValue(clrSeed_II);
unsigned char G_II = GetGValue(clrSeed_II);
unsigned char B_II = GetBValue(clrSeed_II);
unsigned char R, G, B;
// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB图像象素起始位置
lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
// 判断是否是24-bpp位图
if (m_clsDIB.DIBBitCount(lpDIB) != 24)
{
// 提示用户
MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回
return;
}
// 更改光标形状
BeginWaitCursor();
// DIB的宽度
LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 不能用char,也不能用::strcpy()
unsigned char* m_temp;
m_temp = new unsigned char [lLineBytes * lHeight];
// 复制图象数据到中间缓存
for (i = 0; i < lLineBytes * lHeight; i++)
m_temp[i] = *(lpDIBBits + i);
// 对各像素进行灰度转换
for (i = 0; i < lWidth; i++) //被处理像素在i列
{
for (j = 0; j < lHeight; j++) //被处理像素在j行
{
int I, II;
I = II = 0;
for (k = i - 1; k < i + 2; k++) //3*3模版
{
for (l = j - 1; l < j + 2; l++)
{
// 防止内存溢出
if (k >= 0 && l >= 0 && k < lWidth && l < lHeight)
{
// 获取各颜色分量
R = *((unsigned char *)lpDIBBits + l * lLineBytes + k * 3);
G = *((unsigned char *)lpDIBBits + l * lLineBytes + k * 3 + 1);
B = *((unsigned char *)lpDIBBits + l * lLineBytes + k * 3 + 2);
// 判断是否在期望灰度范围内
if (abs(B - B_I) < 10 && abs(G - B_I) < 10 && abs(R - R_I) < 10)
I++;
if (abs(B - B_II) < 10 && abs(G - B_II) < 10 && abs(R - R_II) < 10)
II++;
}
}
}
// 如果周围所有象素灰度相同,当前点一定非边界,可以去掉(设为白色)
if (I == 9 || II == 9)
{
m_temp[j * lLineBytes + i * 3] = 255;
m_temp[j * lLineBytes + i * 3 + 1] = 255;
m_temp[j * lLineBytes + i * 3 + 2] = 255;
}
}
}
// 回存处理结果到DIB
for(i = 0; i < lLineBytes * lHeight; i++)
*(lpDIBBits + i) = m_temp[i];
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 恢复光标
EndWaitCursor();
}
/*************************************************************************
*
* 函数名称:
* TraceDIB()
*
* 参数:
* HDIB hDIB - 待处理的DIB
* COLORREF clrSeed - 种子的RGB值
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数对图象进行边界跟踪
*
************************************************************************/
void CSplitProc::TraceDIB(HDIB hDIB, COLORREF clrSeed)
{
// 循环变量
LONG i;
LONG j;
// 指向源图像的指针
LPBYTE lpSrc;
// 指向缓存图像的指针
LPBYTE lpDst;
//是否找到起始点及回到起始点
bool bFindStartPoint;
//是否扫描到一个边界点
bool bFindPoint;
//起始边界点与当前边界点
CPoint StartPoint, CurrentPoint;
//八个方向和起始扫描方向
int Direction[8][2] = { {-1, 1}, {0, 1}, {1, 1}, {1, 0},
{1, -1}, {0, -1}, {-1, -1}, {-1, 0}};
int BeginDirect;
// 锁定DIB
LPBYTE lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB图像象素起始位置
LPBYTE lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
// 判断是否是24-bpp位图
if (m_clsDIB.DIBBitCount(lpDIB) != 24)
{
// 提示用户
MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回
return;
}
// 更改光标形状
BeginWaitCursor();
// DIB的宽度
LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 暂时分配内存,以保存新图像
HLOCAL hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
if (hNewDIBBits == NULL)
{
// 分配内存失败
return;
}
// 锁定内存
LPBYTE lpNewDIBBits = (LPBYTE)LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (LPBYTE)lpNewDIBBits;
memset(lpDst, (BYTE)255, lLineBytes * lHeight);
//先找到最左上方的边界点
bFindStartPoint = false;
for (j = 0; j < lHeight && !bFindStartPoint; j++)
{
for (i = 0; i < lWidth && !bFindStartPoint; i++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (LPBYTE)(lpDIBBits + lLineBytes * j + i * 3);
if(abs(*lpSrc - GetRValue(clrSeed)) < 10 && abs(*(lpSrc + 1) - GetGValue(clrSeed)) < 10 && abs(*(lpSrc + 2) - GetBValue(clrSeed)) < 10)
{
bFindStartPoint = true;
StartPoint.y = j;
StartPoint.x = i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (LPBYTE)(lpNewDIBBits + lLineBytes * j + i * 3);
*lpDst = (unsigned char) 0;
*(lpDst + 1) = (unsigned char) 0;
*(lpDst + 2) = (unsigned char) 0;
}
}
}
//由于起始点是在左下方,故起始扫描沿左上方向
BeginDirect = 0;
//跟踪边界
bFindStartPoint = false;
//从初始点开始扫描
CurrentPoint.y = StartPoint.y;
CurrentPoint.x = StartPoint.x;
while (!bFindStartPoint)
{
bFindPoint = false;
while (!bFindPoint)
{
if ((CurrentPoint.y + Direction[BeginDirect][1]) >= 0
&& (CurrentPoint.x + Direction[BeginDirect][0]) >= 0
&& (CurrentPoint.y + Direction[BeginDirect][1]) < lHeight
&& (CurrentPoint.x + Direction[BeginDirect][0]) < lWidth)
{
//沿扫描方向查看一个像素
lpSrc = (LPBYTE)(lpDIBBits + lLineBytes * (CurrentPoint.y + Direction[BeginDirect][1])
+ (CurrentPoint.x + Direction[BeginDirect][0]) * 3);
if (abs(*lpSrc - GetRValue(clrSeed)) < 10 && abs(*(lpSrc + 1) - GetGValue(clrSeed)) < 10 && abs(*(lpSrc + 2) - GetBValue(clrSeed)) < 10)
{
bFindPoint = true;
CurrentPoint.y = CurrentPoint.y + Direction[BeginDirect][1];
CurrentPoint.x = CurrentPoint.x + Direction[BeginDirect][0];
if (CurrentPoint.y == StartPoint.y && CurrentPoint.x == StartPoint.x)
bFindStartPoint = true;
lpDst = (LPBYTE)lpNewDIBBits + lLineBytes * CurrentPoint.y + CurrentPoint.x * 3;
*lpDst = (unsigned char) 0;
*(lpDst + 1) = (unsigned char) 0;
*(lpDst + 2) = (unsigned char) 0;
//扫描的方向逆时针旋转两格
BeginDirect--;
if(BeginDirect == -1)
BeginDirect = 7;
BeginDirect--;
if(BeginDirect == -1)
BeginDirect = 7;
}
else
{
//扫描方向顺时针旋转一格
BeginDirect++;
if(BeginDirect == 8)
BeginDirect = 0;
}
}
else
{
bFindPoint = true;
bFindStartPoint = true;
}
}
}
// 复制腐蚀后的图像
memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 恢复光标
EndWaitCursor();
}
/*************************************************************************
*
* 函数名称:
* Threshold()
*
* 参数:
* HDIB hDIB - 待处理的DIB
* int T - 阀值
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数对图象进行阀值化区域分割处理
*
************************************************************************/
void CSplitProc::Threshold(HDIB hDIB, int *nNY)
{
// 循环变量
LONG i;
LONG j;
// 指向DIB的指针
LPBYTE lpDIB;
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB图像象素起始位置
lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
// 判断是否是24-bpp位图
if (m_clsDIB.DIBBitCount(lpDIB) != 24)
{
// 提示用户
MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回
return;
}
// 更改光标形状
BeginWaitCursor();
// DIB的宽度
LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 迭代阀值
int T1, T2;
T1 = 127;
T2 = 0;
// 临时变量
int Temp0, Temp1, Temp2, Temp3;
Temp0 = Temp1 = Temp2 = Temp3 = 0;
while (true)
{
// 计算下一个迭代阀值
for (i = 0; i < T1 + 1; i++)
{
Temp0 += nNY[i] * i;
Temp1 += nNY[i];
}
for (i = T1 + 1; i < 256; i++)
{
Temp2 += nNY[i] * i;
Temp3 += nNY[i];
}
T2 = (Temp0 / Temp1 + Temp2 / Temp3) / 2;
// 看迭代结果是否已收敛
if (T1 == T2)
break;
else
T1 = T2;
}
// 对各像素进行灰度转换
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lLineBytes; j ++)
{
// 读取像素R分量
unsigned char R = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
// 判断R分量是否超出范围
if (R < T1)
R = 0;
else
R = 255;
// 回写处理完的R分量
*((unsigned char *)lpDIBBits + lLineBytes * i + j) = R;
j++;
// 读取像素G分量
unsigned char G = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
// 判断G分量是否超出范围
if (G < T1)
G = 0;
else
G = 255;
// 回写处理完的G分量
*((unsigned char *)lpDIBBits + lLineBytes * i + j) = G;
j++;
// 读取像素B分量
unsigned char B = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
// 判断B分量是否超出范围
if (B < T1)
B = 0;
else
B = 255;
// 回写处理完的B分量
*((unsigned char *)lpDIBBits + lLineBytes * i + j) = B;
}
}
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 恢复光标
EndWaitCursor();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -