博客
关于我
OpenCV学习(13) 细化算法(1)(转)
阅读量:791 次
发布时间:2023-02-23

本文共 4748 字,大约阅读时间需要 15 分钟。

程序编码参考经典的细化或者骨架算法文章

转载链接:http://www.cnblogs.com/mikewolf2002/p/3321732.html

程序编码参考经典的细化或者骨架算法文章

它的原理也很简单:

我们对一副二值图像进行骨架提取,就是删除不需要的轮廓点,只保留其骨架点。假设一个像素点,我们定义该点为p1,则它的八邻域点p2-p9位置如下图所示,该算法考虑p1点邻域的实际情况,以便决定是否删除p1点。假设我们处理的为二值图像,背景为黑色,值为0,要细化的前景物体像素值为1。

算法的描述如下:

首先复制源图像到目标图像,然后建立一个临时图像,接着执行下面操作:

  • 把目标图像复制给临时图像,对临时图像进行一次扫描,对于不为0的点,如果满足以下四个条件,则在目标图像中删除该点(就是设置该像素为0),这里p2,...,p9是对应位置的像素灰度值(其为1或者0)。
  • a. 2 ≤ p2+p3+p4+p5+p6+p7+p8+p9 ≤6

    大于等于2会保证p1点不是端点或孤立点,因为删除端点和孤立点是不合理的,小于等于6保证p1点是一个边界点,而不是一个内部点。等于0的时候,周围没有等于1的像素,所以p1为孤立点,等于1的时候,周围只有1个灰度等于1的像素,所以是端点。

    b. p2-p9的排列顺序中,01模式的数量为1,比如下面的图中,有p2p3 => 01, p6p7 => 01,所以该像素01模式的数量为2。

    之所以要01模式数量为1,是要保证删除当前像素点后的连通性。比如下面的图中,01模式数量大于1,如果删除当前点p1,则连通性不能保证。

    c. P2p4p6 = 0

    d. p4p6p8 = 0

    在第一次子迭代中,只是移去东南的边界点,而不考虑西北的边界点,注意p4,p6出现了2次,就是说它们有一个为0,则c,d就满足。

    1. 接下来,把目标图像再次复制到临时图像,接着对临时图像进行一次扫描,如果不为0的点它的八邻域满足以下4个条件,则在目标图像中删除该点(就是设置该像素为0)
    2. a. 2 ≤ p2+p3+p4+p5+p6+p7+p8+p9 ≤6

      b. p2-p9的排列顺序中,01模式的数量(这里假设二值图非零值为1)为1。

      c. p2p4p8 = 0

      d. p2p6p8 = 0

      第二次迭代则相反,会移去西北的边界点,注意p2,p8出现了2次,就是说它们有一个为0,则c,d就满足。

      执行完上面两个步骤后,就完成了一次细化算法,我们可以多次迭代执行上述过程,得到最终的骨架图。

      细化算法代码如下:

      void gThin::cvThin(cv::Mat& src, cv::Mat& dst, int intera) {    if(src.type()!=CV_8UC1) {        printf("只能处理二值或灰度图像\n");        return;    }    if(dst.data!=src.data) {        src.copyTo(dst);    }    int i, j, n;    int width = src.cols -1;    int height = src.rows -1;    int step = src.step;    int p2,p3,p4,p5,p6,p7,p8,p9;    uchar* img;    bool ifEnd;    int A1;    cv::Mat tmpimg;    for(n = 0; n < intera; n++) {        dst.copyto(tmpimg);        ifEnd = false;        img = tmpimg.data;        for(i = 1; i < height; i++) {            img += step;            for(j = 1; j < width; j++) {                if(img[0] != 0) {                    A1++;                    if(img[-step] == 0 && img[-step+1] != 0) { A1++; }                    if(img[-step+1] == 0 && img[1] != 0) { A1++; }                    if(img[1] == 0 && img[step+1] != 0) { A1++; }                    if(img[step+1] == 0 && img[step] != 0) { A1++; }                    if(img[step] == 0 && img[step-1] != 0) { A1++; }                    if(img[step-1] == 0 && img[-1] != 0) { A1++; }                    if(img[-1] == 0 && img[-step-1] != 0) { A1++; }                    if(img[-step-1] == 0 && img[-step] != 0) { A1++; }                    p2 = img[-step] != 0 ? 1 : 0;                    p3 = img[-step+1] != 0 ? 1 : 0;                    p4 = img[1] != 0 ? 1 : 0;                    p5 = img[step+1] != 0 ? 1 : 0;                    p6 = img[step] != 0 ? 1 : 0;                    p7 = img[step-1] != 0 ? 1 : 0;                    p8 = img[-1] != 0 ? 1 : 0;                    p9 = img[-step-1] != 0 ? 1 : 0;                    if((p2+p3+p4+p5+p6+p7+p8+p9) > 1 && (p2+p3+p4+p5+p6+p7+p8+p9) < 7 && A1 == 1) {                        if((p2 == 0 || p4 == 0 || p6 == 0) && (p4 == 0 || p6 == 0 || p8 == 0)) {                            dst.at
      (i,j) = 0; ifEnd = true; } } } } } if(!ifEnd) break; dst.copyTo(tmpimg); img = tmpimg.data; for(i = 1; i < height; i++) { img += step; for(j = 1; j < width; j++) { if(img[0] != 0) { A1++; if(img[-step] == 0 && img[-step+1] != 0) { A1++; } if(img[-step+1] == 0 && img[1] != 0) { A1++; } if(img[1] == 0 && img[step+1] != 0) { A1++; } if(img[step+1] == 0 && img[step] != 0) { A1++; } if(img[step] == 0 && img[step-1] != 0) { A1++; } if(img[step-1] == 0 && img[-1] != 0) { A1++; } if(img[-1] == 0 && img[-step-1] != 0) { A1++; } if(img[-step-1] == 0 && img[-step] != 0) { A1++; } p2 = img[-step] != 0 ? 1 : 0; p3 = img[-step+1] != 0 ? 1 : 0; p4 = img[1] != 0 ? 1 : 0; p5 = img[step+1] != 0 ? 1 : 0; p6 = img[step] != 0 ? 1 : 0; p7 = img[step-1] != 0 ? 1 : 0; p8 = img[-1] != 0 ? 1 : 0; p9 = img[-step-1] != 0 ? 1 : 0; if((p2+p3+p4+p5+p6+p7+p8+p9) > 1 && (p2+p3+p4+p5+p6+p7+p8+p9) < 7 && A1 == 1) { if((p2 == 0 || p4 == 0 || p8 == 0) && (p2 == 0 || p6 == 0 || p8 == 0)) { dst.at
      (i,j) = 0; ifEnd = true; } } } } } if(!ifEnd) break; }}

      下面是三次细化的结果,可以看出在垂直方向H变短了,感觉这是不完美的地方。

      下面我们对两个汉字进行5次迭代细化,结果如下:

      程序代码:工程FirstOpenCV11

      转载于:https://www.cnblogs.com/mobileliker/articles/4059882.html

    你可能感兴趣的文章
    Objective-C实现基于模板的双向链表(附完整源码)
    查看>>
    Objective-C实现备忘录模式(附完整源码)
    查看>>
    Objective-C实现复制粘贴文本功能(附完整源码)
    查看>>
    Objective-C实现复数类+-x%(附完整源码)
    查看>>
    Objective-C实现多组输入(附完整源码)
    查看>>
    Objective-C实现子集总和算法(附完整源码)
    查看>>
    Objective-C实现字符串IP地址转DWORD地址(附完整源码)
    查看>>
    Objective-C实现字符串jaro winkler算法(附完整源码)
    查看>>
    Objective-C实现字符串manacher马拉车算法(附完整源码)
    查看>>
    Objective-C实现字符串wildcard pattern matching通配符模式匹配算法(附完整源码)
    查看>>
    Objective-C实现字符串word patterns单词模式算法(附完整源码)
    查看>>
    Objective-C实现字符串Z 函数或 Z 算法(附完整源码)
    查看>>
    Objective-C实现字符串加解密(附完整源码)
    查看>>
    Objective-C实现字符串复制功能(附完整源码)
    查看>>
    Objective-C实现完整的ComplexNumber复数类(附完整源码)
    查看>>
    Objective-C实现将位转换为浮点数bitsToFloat算法(附完整源码)
    查看>>
    Objective-C实现将彩色图像转换为负片算法(附完整源码)
    查看>>
    Objective-C实现将给定的 utf-8 字符串编码为 base-16算法(附完整源码)
    查看>>
    Objective-C实现巴比伦平方根算法(附完整源码)
    查看>>
    Objective-C实现度到弧度算法(附完整源码)
    查看>>