查找边缘Moore neighboorhood

         如何查找连通域的外轮廓,OpenCv使用FindContours,比较复杂,对于一些简单的情况可使用Moore neighboorhood算法的实现,方便与OpenCv结构使用。

伪代码如下

 Begin
  Set B to be empty.
  From bottom to top and left to right scan the cells of T until a black pixel, s, of P is found.
  Insert s in B.
  Set the current boundary point p to s i.e. p=s
  b = the pixel from which s was entered during the image scan.
  Set c to be the next clockwise pixel (from b) in M(p).
  While c not equal to s do
    If c is black
      insert c in B
      b = p
      p = c
      (backtrack: move the current pixel c to the pixel from which p was entered)
      c = next clockwise pixel (from b) in M(p).
    else
      (advance the current pixel c to the next clockwise pixel in M(p) and update backtrack)
      b = c
      c = next clockwise pixel (from b) in M(p).
    end While
  End
C++和OpenCv实现代码如下

#include "core\core.hpp"
#include "highgui\highgui.hpp"
using namespace std;

cv::Point getCWofP(cv::Point & b,cv::Point & p)//逆时针查找
{
    cv::Point rt;
    if(b.x<=p.x&&b.y==p.y-1)
    {
        rt.y=b.y;
        rt.x=b.x+1;
    }
    else
    {
        if(b.x==p.x+1&&b.y<=p.y)

        {
            rt.x=b.x;
            rt.y=b.y+1;
        }
        else
        {
            if(b.x>=p.x&&b.y==p.y+1)
            {
                rt.y=b.y;
                rt.x=b.x-1;
            }
            else
            {
                rt.x=b.x;
                rt.y=b.y-1;
            }
        }
    }
    return rt;

}

vector<cv::Point> Execuse(cv::Mat T)        //查找T中连通域的轮廓,假设T中只有一个连通域
{
    cv::Point p;
    cv::Point b;
    cv::Point c;
    cv::Point s;

    int wd=T.cols;
    int ht=T.rows;
    vector<cv::Point> B;
    for (int i=0;i<ht;i++)
    {
        int fd=0;
        for (int j=0;j<wd;j++)
        {
            char c=T.at<char>(i,j);
            if(c==0 ) //black
            {
                s.x=i;
                s.y=j;
                fd=1;
                break;
            }

        }
        if(fd)
            break;
    }

    B.push_back(s);
    p=s;
    b.x=s.x;
    b.y=s.y-1;

    c=getCWofP(b,p);
    while (c.x!=s.x||s.y!=c.y)
    {
        if(T.at<char>(c.x,c.y)==0) //c是黑色
        {
            B.push_back(c);
            b=p;
            p=c;
            c=getCWofP(b,p);
        }
        else
        {
            b=c;
            c=getCWofP(b,p);
        }
    }
    return B;

}

int main()
{
    int i,j;
    cv::Point c ;
    cv::Mat b(100,100,CV_8UC1,255);
    for(i=10;i<50;i++)
        for(j=20;j<60;j++)
            b.at<char>(i,j)=0;                   //置轮通域
    cv::namedWindow("origin",0);
    cv::imshow("origin",b);
    vector<cv::Point> contour_edge=Execuse(b);
    cv::Mat b_p(100,100,CV_8UC1,255);
    for(i=0;i<contour_edge.size();i++)
        b_p.at<char>(contour_edge[i].x,contour_edge[i].y)=0;
    cv::namedWindow("moore",0);
    cv::imshow("moore",b_p);
    cv::waitKey();
    cv::destroyAllWindows();
    return 1;

}

下图为原始图片和寻找的外轮廓图片

MATLAB代码为

function [MooreNeighbour top]=findBoundary(image)%image input
    [ht wd]=size(image);
    imshow(image)
    MooreNeighbour=zeros(ht*wd,2);
    p=zeros(1,2);
    c=zeros(1,2);
    b=zeros(1,2);
    s=zeros(1,2);
    top=0;
    for i=1:ht
        fd=0;
        for j=1:wd
            if(image(i,j)==0 )
                s(1)=i;
                s(2)=j;
                fd=1;
                top=1;
                MooreNeighbour(top,1)=i;
                MooreNeighbour(top,2)=j;
                break;
            end
        end
        if(fd)
            break;
        end
    end

    
    p(1)=s(1);
    p(2)=s(2);
    b(1)=p(1);
    b(2)=p(2)-1;

    c=getCWofP(b,p);
    while (c(1)~=s(1)||s(2)~=c(2))
        if(image(c(1),c(2))==0) %c is black
            top=top+1;
            MooreNeighbour(top,:)=c;
            b(1)=p(1);
            b(2)=p(2);
            p(1)=c(1);
            p(2)=c(2);
            c=getCWofP(b,p);
        else
            b(1)=c(1);
            b(2)=c(2);
            c=getCWofP(b,p);
        end
    end
end
 
function c=getCWofP(b,p)
    if(b(1)<=p(1)&&b(2)==p(2)-1)
        c(2)=b(2);
        c(1)=b(1)+1;
    else
        if(b(1)==p(1)+1&&b(2)<=p(2))
            c(1)=b(1);
            c(2)=b(2)+1;
        else
            if(b(1)>=p(1)&&b(2)==p(2)+1)
                c(2)=b(2);
                c(1)=b(1)-1;
            else
                c(1)=b(1);
                c(2)=b(2)-1;
            end
        end
    end
end





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值