256位色的图像
内容是等高线
求细化算法!多谢

解决方案 »

  1.   

    我刚写的论文就是关于提取骨架的,
    如果发表了我就把偶的算法给你,比一般方法都快哦^o^我现在先告诉你一个经典的算法吧:
    Burning Algorithm:
    对一个图形,先得到它的边界,然后去掉边界的像素;
    再去掉剩下的图形的边界的像素,....,
    这个过程就如同火种从边界各点同时开始向里燃烧,
    保留燃烧相遇的点,这些点的集合就是图形的骨架。
    (也就是完成了物体的细化)。
      

  2.   

    有一个四围判断法,简单代码如下:void CCheDoc::OnThining()   //数学形态学之图像细化  (对黑目标进行处理)
    {
    // 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);

    }
      

  3.   

    《Visual C++数字图像模式识别技术及工程实践》
      

  4.   

    见我的文章,图像细化http://blog.csdn.net/sboom
      

  5.   

    BOOL WINAPI ThiningDIB(LPSTR lpDIBBits,LONG lWidth,LONG lHeight)
    {
    //指向原图像的指针
    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();
    }每回调用完之后,原图就不见了,
      

  6.   

    我用的这个函数,
    在菜单里是这样调用的
    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();
    }每回调用完之后,原图就不见了,
      

  7.   

    我发现了,是我的机子不能运行
    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应该怎么改??
      

  8.   

    细化算法 那个好?Hilditch细化算法Pavlidis细化算法Rosenfeld细化算法