matlab求0-1封闭区域围成的面积

来源:互联网 发布:彩票预测app源码 编辑:程序博客网 时间:2024/04/28 02:02
做毕业设计需要用到这个,所以自己写了个函数。函数作用是求两张轮廓线图片不一致地方所围成区域的周长和面积。后面还要优化,先把大致结构贴在这里:
function area_peri(a,b)%输入为两张轮廓图像    n = 481;m = 321;%n,m分别为图像的高和宽    pic1 = imread(a);    pic2 = imread(b);    pic1 = logical(pic1);    pic2 = logical(pic2);    pic = bitxor(pic1,pic2);%将两幅图像进行异或运算,求出边界    perimeter = bwarea(pic);%边界的像素点个数即周长    for i = 1:n,%遍历整个图像区域,求出边界围成面积的像素总个数即面积        flag = 0;        for j = 1:m,            if flag == 0                if pic(i,j) == 1                    flag = 1;                end            else                if pic(i,j) == 1                    flag = 0;                else                    pic(i,j) = 1;                end            end            end    end    area = bwarea(pic);    fprintf('area = %f\nperimeter = %f\n',area,perimeter);    imshow(pic);end

此函数的问题:对轮廓精确的要求较高(每一行必须修改偶数个像素,且边界必须是奇数;即奇数+奇数=偶数)

上述函数显然适用范围太过狭隘,轮廓不可能总会“碰巧”符合上述条件。实际上,搜索的思路也是自然而然的:即在封闭区域内选择一个种子点,然后在此点开始深搜(广搜),统计搜索到的像素数。按照此思路,我先在matlab上写了一个,但是发现matlab递归的效率太低了(它默认的递归次数是500次,而且所用时间也非常长)。所以还是记录下C代码:

#include <stdio.h>#include <string.h>#define N 488int im[N][N],n=321,m=481,flag[N][N];//flag为边界的索引int ori[8][2] = {{-1,0},{0,1},{1,0},{0,-1},{-1,1},{1,1},{1,-1},{-1,-1}};int check(int x,int y){//测试边界点是否在图像范围内if(x<0||y<0||x==n||y==m)return 0;return 1;}void plant(int x,int y,int top){//填充边界,不同的封闭区域边界设置为不同的值int i;for(i = 0;i<8;i++){int xx = x+ori[i][0];int yy = y+ori[i][1];if(check(xx,yy) && im[xx][yy] == 1 && !flag[xx][yy]){flag[xx][yy] = top;plant(xx,yy,top);}}}void dfs(int x,int y){//深搜求封闭区域面积;搜到的部分填充为1int i;for(i = 0;i<4;i++){int xx = x+ori[i][0];int yy = y+ori[i][1];if(check(xx,yy) && im[xx][yy] == 0){im[xx][yy] = 1;dfs(xx,yy);}}}int isroot(int x,int y){//判断当前像素能否当作种子像素;判断标准,距此点四周最近的坐标点都是同一块区域的边界。int i,temp;for(i = x;i>=0;i--)if(flag[i][y]){temp = flag[i][y];break;}if(i == -1)return 0;for(i = x;i<n;i++)if(flag[i][y]){if(flag[i][y] != temp)return 0;break;}if(i==n)return 0;for(i = y;i>=0;i--)if(flag[x][i]){if(flag[x][i] != temp)return 0;break;}if(i==-1)return 0;for(i = y;i<m;i++)if(flag[x][i]){if(flag[x][i]!= temp)return 0;return 1;}if(i==m)return 0;return 1;}int main(){int i,j,perimeter=0,area = 0;int top = 1;freopen("a.txt","r",stdin);memset(flag,0,sizeof(flag));for(i = 0;i<n;i++)for(j = 0;j<m;j++){scanf("%d",&im[i][j]);perimeter += im[i][j];}for(i = 0;i<n;i++)//填充边界,并为区域编号for(j = 0;j<m;j++)if(!flag[i][j] && im[i][j] == 1){flag[i][j] = top;plant(i,j,top);top++;}for(i = 1;i<n;i++){//找种子点,深搜for(j = 1;j<m;j++){if(im[i][j]==0&&isroot(i,j)){//printf("this root is %d %d\n",i,j);im[i][j] = 1;dfs(i,j);}}}for(i = 0;i<n;i++)for(j = 0;j<m;j++)if(im[i][j] == 1)area++;printf("Perimeter is %d\n",perimeter);printf("Area is %d\n",area);return 0;}

0 0
原创粉丝点击