256位色的图像
内容是等高线
求细化算法!多谢
内容是等高线
求细化算法!多谢
解决方案 »
- DCT变换
- wince5.0 下读取电池电量,找不到GetSystemPowerStatusEx2
- 150分,求CInternetSession上传文件的实例代码
- CreatePen为什么不起作用呢?
- 如何编程让收集的数据转变成曲线在界面上输出
- 一段代码
- 高分求一个ListView_GetItemRect问题
- 请问关于telnet 编程
- 这个unresolved external symbol连接错误是怎么回事?
- 有专门讲API使用方法的书吗?谢谢!
- 哪位仁兄用过visual c++ 数字图像牧师识别技术及工程实践中的细化算法,懂这方面的进!!
- 不懂timeSetEvent函数的参数uResolution延时精度有什么用
如果发表了我就把偶的算法给你,比一般方法都快哦^o^我现在先告诉你一个经典的算法吧:
Burning Algorithm:
对一个图形,先得到它的边界,然后去掉边界的像素;
再去掉剩下的图形的边界的像素,....,
这个过程就如同火种从边界各点同时开始向里燃烧,
保留燃烧相遇的点,这些点的集合就是图形的骨架。
(也就是完成了物体的细化)。
{
// TODO: Add your command handler code here
int count, i, j, m, n;
int CutEveryTime=1;
BYTE by;
//因为细化算法时间较长,所以显示等待光标
BeginWaitCursor();
//若四个条件同时满足,则删除该点
BOOL condition1, condition2, condition3, condition4; BYTE plate[5][5]; while(CutEveryTime!=0)
{
CutEveryTime=0;
for(i=2; i<Height-2; i++) //外围不处理
for(j=2; j<Width-2; j++)
{
condition1 = condition2 = condition3 = condition4 = false; //将数据读入plate
for(m=-2; m<2; m++)
for(n=-2; n<2; n++)
{
by=oldposigrey2.GetAt((i+m)*Width+(j+n));
plate[m+2][n+2]=by;
} //如果当前点为白色,则跳过
if(plate[2][2]==255)
continue;
//判断2<=NZ(P1)<=6
count=0;
for(m=1; m<=3; m++)
for(n=1; n<=3; n++)
{
if(plate[m][n]==0)
count++;
} if(plate[2][2]==0)
count--; if (count>=2&&count<=6)
condition1=true; //判断Z0(P1)=1
count=0;
if(plate[1][2]==255&&plate[1][1]==0)
count++;
if(plate[1][1]==255&&plate[2][1]==0)
count++;
if(plate[2][1]==255&&plate[3][1]==0)
count++;
if(plate[3][1]==255&&plate[3][2]==0)
count++;
if(plate[3][2]==255&&plate[3][3]==0)
count++;
if(plate[3][3]==255&&plate[2][3]==0)
count++;
if(plate[2][3]==255&&plate[1][3]==0)
count++;
if(plate[1][3]==255&&plate[1][2]==0)
count++; if(count==1)
condition2=true; //判断P2*P4*P8=0 OR Z0(P2)!=1
if(plate[1][2]==255||plate[2][1]==255||plate[2][3]==255)
condition3=true;
else
{
count=0;
if(plate[0][2]==255&&plate[0][1]==0)
count++;
if(plate[0][1]==255&&plate[1][1]==0)
count++;
if(plate[1][1]==255&&plate[2][1]==0)
count++;
if(plate[2][1]==255&&plate[2][2]==0)
count++;
if(plate[2][2]==255&&plate[2][3]==0)
count++;
if(plate[2][3]==255&&plate[1][3]==0)
count++;
if(plate[1][3]==255&&plate[0][3]==0)
count++;
if(plate[0][3]==255&&plate[0][2]==0)
count++; if(count!=1)
condition3=true; } //判断P2*P4*P6=0 OR Z0(P4)!=1
if(plate[1][2]==255||plate[2][1]==255||plate[3][2]==255)
condition4=true;
else
{
count=0;
if(plate[1][1]==255&&plate[1][0]==0)
count++;
if(plate[1][0]==255&&plate[2][0]==0)
count++;
if(plate[2][0]==255&&plate[3][0]==0)
count++;
if(plate[3][0]==255&&plate[3][1]==0)
count++;
if(plate[3][1]==255&&plate[3][2]==0)
count++;
if(plate[3][2]==255&&plate[2][2]==0)
count++;
if(plate[2][2]==255&&plate[1][2]==0)
count++;
if(plate[1][2]==255&&plate[1][1]==0)
count++; if(count!=1)
condition4=true;
} //如果条件均满足,则将该点从物体中删除
if(condition1 && condition2 && condition3 && condition4)
{
posigrey2.SetAt(i*Width+j, 255);
CutEveryTime++;
} }
oldposigrey2.Copy(posigrey2); } //结束显示等待光标
EndWaitCursor(); UpdateAllViews(NULL);
}
{
//指向原图像的指针
LPSTR lpSrc; //指向缓存图像的指针
LPSTR lpDst; //指向缓存DIB图像的指针
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits; //脏标记
BOOL bModified; //循环变量
long i;
long j;
int n;
int m; //四个条件
BOOL bCondition1;
BOOL bCondition2;
BOOL bCondition3;
BOOL bCondition4; //计数器
unsigned char nCount; //像素值
unsigned char pixel; //5*5相邻区域像素值
unsigned char neighbour[5][5]; //暂时分配内存,以保存新图像
hNewDIBBits=LocalAlloc(LHND,lWidth*lHeight); if(hNewDIBBits==NULL)
{
//分配内存失败
return FALSE;
} //锁定内存
lpNewDIBBits=(char*)LocalLock(hNewDIBBits); //初始化新分配的内存,设定初始值为255
lpDst=(char*)lpNewDIBBits;
memset(lpDst,(BYTE)255,lWidth*lHeight); bModified=TRUE; while(bModified)
{
bModified=FALSE;
//初始化新分配的内存,设定初始值为255
lpDst=(char*)lpNewDIBBits;
memset(lpDst,(BYTE)255,lWidth*lHeight);
for(j=2;j<lHeight-2;j++)
{
for(i=2;i<lWidth-2;i++)
{
bCondition1=FALSE;
bCondition2=FALSE;
bCondition3=FALSE;
bCondition4=FALSE; //由于使用5*5的结构元素,为防止越界,所以不处理外围的几行和几列像素 //指向原图倒数第j行,第i个像素的指针
lpSrc=(char*)lpDIBBits+lWidth*j+i; //指向目标图像倒数第j行,第i个像素的指针
lpDst=(char*)lpNewDIBBits+lWidth*j+i; //取得当前指针处的像素值,注意要转换为unsigned char型
pixel=(unsigned char)*lpSrc; //目标图像中含有0和255外的其他灰度值
if(pixel!=255&&*lpSrc!=0)
return FALSE; //如果原图像中当前点为白色,则跳过
else if(pixel==255)
continue; //获取当前点相符的5*5区域内像素值,0代表白色,1代表黑色
for(m=0;m<5;m++)
{
for(n=0;n<5;n++)
{
neighbour[m][n]=(255-(unsigned char)*(lpSrc+((4-m)-2)*lWidth+n-2))/255;
}
}
//neighbour[][]
//逐个判断条件。
//判断2<=NZ(PI)<=6
nCount=neighbour[1][1]+neighbour[1][2]+neighbour[1][3]\
+neighbour[2][1]+neighbour[2][3]+\
+neighbour[3][1]+neighbour[3][2]+neighbour[3][3];
if(nCount>=2&&nCount<=6)
bCondition1=TRUE; //判断Z0(P1)=1
nCount=0;
if(neighbour[1][2]==0&&neighbour[1][1]==1)
nCount++;
if(neighbour[1][1]==0&&neighbour[2][1]==1)
nCount++;
if(neighbour[2][1]==0&&neighbour[3][1]==1)
nCount++;
if(neighbour[3][1]==0&&neighbour[3][2]==1)
nCount++;
if(neighbour[3][2]==0&&neighbour[3][3]==1)
nCount++;
if(neighbour[3][3]==0&&neighbour[2][3]==1)
nCount++;
if(neighbour[2][3]==0&&neighbour[1][3]==1)
nCount++;
if(neighbour[1][3]==0&&neighbour[1][2]==1)
nCount++;
if(nCount==1)
bCondition2=TRUE; //判断P2*P4*P8=0 or Z0(p2)!=1
if(neighbour[1][2]*neighbour[2][1]*neighbour[2][3]==0)
bCondition3=TRUE;
else
{
nCount=0;
if(neighbour[0][2]==0&&neighbour[0][1]==1)
nCount++;
if(neighbour[0][1]==0&&neighbour[1][1]==1)
nCount++;
if(neighbour[1][1]==0&&neighbour[2][1]==1)
nCount++;
if(neighbour[2][1]==0&&neighbour[2][2]==1)
nCount++;
if(neighbour[2][2]==0&&neighbour[2][3]==1)
nCount++;
if(neighbour[2][3]==0&&neighbour[1][3]==1)
nCount++;
if(neighbour[1][3]==0&&neighbour[0][3]==1)
nCount++;
if(neighbour[0][3]==0&&neighbour[0][2]==1)
nCount++;
if(nCount!=1)
bCondition3=TRUE;
} //判断P2*P4*P6=0 or Z0(p4)!=1
if(neighbour[1][2]*neighbour[2][1]*neighbour[3][2]==0)
bCondition4=TRUE;
else
{
nCount=0;
if(neighbour[1][1]==0&&neighbour[1][0]==1)
nCount++;
if(neighbour[1][0]==0&&neighbour[2][0]==1)
nCount++;
if(neighbour[2][0]==0&&neighbour[3][0]==1)
nCount++;
if(neighbour[3][0]==0&&neighbour[3][1]==1)
nCount++;
if(neighbour[3][1]==0&&neighbour[3][2]==1)
nCount++;
if(neighbour[3][2]==0&&neighbour[2][2]==1)
nCount++;
if(neighbour[2][2]==0&&neighbour[1][2]==1)
nCount++;
if(neighbour[1][2]==0&&neighbour[1][1]==1)
nCount++;
if(nCount!=1)
bCondition4=TRUE;
}
if(bCondition1&&bCondition2&&bCondition3&&bCondition4)
{
*lpDst=(unsigned char)255;
bModified=TRUE;
}
else
{
*lpDst=(unsigned char)0;
}
}
} //复制腐蚀后的图像
memcpy(lpDIBBits,lpNewDIBBits,lWidth*lHeight); }
//复制腐蚀后的图像
memcpy(lpDIBBits,lpNewDIBBits,lWidth*lHeight); //释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits); //返回
return TRUE;
}我用的这个函数,
在菜单里是这样调用的
void CCh1_1View::OnGrapheditThining()
{
//获取文档
CCh1_1Doc* pDoc=GetDocument(); //指向DIB的指针
LPSTR lpDIB; //指向DIB像素指针
LPSTR lpDIBBits; //锁定DIB
lpDIB=(LPSTR)::GlobalLock((HGLOBAL)pDoc->GetHDIB()); //判断是否是8-bpp位图
if(::DIBNumColors(lpDIB)!=256)
{
//提示用户
MessageBox("目前只支持256色位图的细化运算!","系统提示",MB_ICONINFORMATION|MB_OK); //解除锁定
::GlobalUnlock((HGLOBAL)pDoc->GetHDIB()); //返回
return;
} //更改光标形状
BeginWaitCursor(); //找到DIB图像像素起始位置
lpDIBBits=::FindDIBBits(lpDIB); //调用ThiningDIB()函数对DIB进行细化
if(ThiningDIB(lpDIB,::DIBWidth(lpDIB),::DIBHeight(lpDIB)))
{
//设置脏标记
pDoc->SetModifiedFlag(TRUE); //更新视图
pDoc->UpdateAllViews(NULL);
}
else
{
//提示用户
MessageBox("分配内存失败或者图像中含有0或255之外的像素值!","系统提示",
MB_ICONINFORMATION|MB_OK);
} //解除锁定
::GlobalUnlock((HGLOBAL)pDoc->GetHDIB()); //恢复光标
EndWaitCursor();
}每回调用完之后,原图就不见了,
在菜单里是这样调用的
void CCh1_1View::OnGrapheditThining()
{
//获取文档
CCh1_1Doc* pDoc=GetDocument(); //指向DIB的指针
LPSTR lpDIB; //指向DIB像素指针
LPSTR lpDIBBits; //锁定DIB
lpDIB=(LPSTR)::GlobalLock((HGLOBAL)pDoc->GetHDIB()); //判断是否是8-bpp位图
if(::DIBNumColors(lpDIB)!=256)
{
//提示用户
MessageBox("目前只支持256色位图的细化运算!","系统提示",MB_ICONINFORMATION|MB_OK); //解除锁定
::GlobalUnlock((HGLOBAL)pDoc->GetHDIB()); //返回
return;
} //更改光标形状
BeginWaitCursor(); //找到DIB图像像素起始位置
lpDIBBits=::FindDIBBits(lpDIB); //调用ThiningDIB()函数对DIB进行细化
if(ThiningDIB(lpDIB,::DIBWidth(lpDIB),::DIBHeight(lpDIB)))
{
//设置脏标记
pDoc->SetModifiedFlag(TRUE); //更新视图
pDoc->UpdateAllViews(NULL);
}
else
{
//提示用户
MessageBox("分配内存失败或者图像中含有0或255之外的像素值!","系统提示",
MB_ICONINFORMATION|MB_OK);
} //解除锁定
::GlobalUnlock((HGLOBAL)pDoc->GetHDIB()); //恢复光标
EndWaitCursor();
}每回调用完之后,原图就不见了,
memset
memcpy
程序我把memcpy改成
for(i=0;i<lHeight;i++)
{
for(j=0;j<lWidth;j++)
{
lpTemp=(unsigned char*)lpNewDIBBits+lWidth*i+j;
lpDIBBits=(char*)lpTemp-lWidth*i-j;
}
}
memset应该怎么改??