• 21天学习挑战赛--图像物体的边界


    活动地址:CSDN21天学习挑战赛

    题目描述

    给一个二维数组M行N列,数组中的数字代表图片的像素,为了简化问题,仅包含像素1和5两种像素,每种像素代表一个物体,将两个不同物体相邻的格子称为边界,求像素1代表的边界个数。(0

    其中像素1代表的物体边界是指像素为1并且与像素5相邻的格子,而相邻的概念是指八个方向(上、下、左、右、左上、左下、右上、右下)的相近。

    如上图,其中黄色部分即为边界,根据相邻的概念,黄色的格子组成了两个边界。

    上图中的黄色格子据相邻的概念只有一个边界。

    输入示例

    6 6

    1 1 1 1 1 1

    1 5 1 1 1 1

    1 1 1 1 1 1

    1 1 1 1 1 1

    1 1 1 1 1 1

    1 1 1 1 1 5

    输出

    2

    解析见上图

    思考

    解决这个问题可以分为两步:

    • 确定边界格子

    • 判断边界格子所属边界的个数

    那么就有了解决问题的思路,第一步确定边界格子,可以将5周围的格子标记出来,这里是数组,那就赋一个不是1、5的值就好了,这里用2标记,于是我们有了:

    2 2 2 1 1 1

    2 5 2 1 1 1

    2 2 2 1 1 1

    1 1 1 1 1 1

    1 1 1 1 2 2

    1 1 1 1 2 5

    这样所有的边界格子被标记出来了,然后第二步判断边界格子所属边界,那么就是找2的格子,找到一个2的格子a便立即根据相邻规律将所有与格子a相邻的所有为2的格子变为3,那么找到2的次数便是边界的个数。

    3 3 3 1 1 1

    3 5 3 1 1 1

    3 3 3 1 1 1

    1 1 1 1 1 1

    1 1 1 1 3 3

    1 1 1 1 3 5

    代码

    根据上面的思考,里面都有一个给相邻格子赋值的操作,先抽象成方法。

    	/**给相邻的格子赋值,pixel为当前值,target为目标值,只有当前值为pixel才会有赋值操作
    	  *i,j分别对应数组中中心点的位置
    	  *recursion确定是否为递归
    	  */
    public void put(int i, int j, int[][] array, int pixel, int target, boolean recursion) {
        //遍历上、中、下
        for (int a=-1;a<=1;a++){
            //遍历左、中、右
            for (int b=-1;b<=1;b++) {
                //确保数组下标不越界,并且数组当前位置的值为指定像素值pixel
                if (i+a < array.length && i+a >= 0 &&
                j+b < array[0].length && j+b >= 0 &&
                array[i+a][j+b] == pixel) {
                    array[i+a][j+b] = target;
                    //递归
                    if (recursion) {
                        put(i+a,j+b, array, pixel, target, true);
                    }
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    此处定义的方法 put() 主要功能是将数组当前位置的所有相邻部分并且其像素pixel为指定值的格子赋上目标值target,当递归recursion为true时,会将根据相邻规则画出的一个块都赋上目标值。

    第二步,判断边界个数,用上面的方法递归计算边界的个数。

    public static void main(String[] args) {
        //初始化数组
        int[][] a = new int[6][6];
        for (int i=0;i<a.length;i++) {
            for (int j=0;j<a[0].length;j++){
                a[i][j] = 1;
            }
        }
        a[1][1] = 5;
        a[5][5] = 5;
        
        //标记像素5的边界,用2标记
        for (int i=0;i<a.length;i++) {
            for (int j=0;j<a[0].length;j++){
                if (a[i][j] == 5)
                    //调用put方法标记边界
                    put(i,j,a,1,2,false);
            }
        }
        
        //统计边界个数
        int count = 0;
        for (int i=0;i<a.length;i++) {
            for (int j=0;j<a[0].length;j++){
                //找到2的格子,并递归标记
                if (a[i][j] == 2) {
                    put(i, j, a, 2, 3, true);
                    count ++;
                }
            }
        }
        System.out.println("边界个数:" + count);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    其实这里还可以尝试用不同的值标记不同的边界,那么也许更明显,但是在尝试过程中,一定要避免2、1之类的已经出现的值,可能让递归陷入死循环,会报栈溢出错误。
    至此,问题解决。

  • 相关阅读:
    docker创建tomcat镜像与COPY与ADD 关键字的使用
    深圳芯片一级代理商使全球芯片市场堕入阻滞
    Linux gcc和make学习
    逐鹿澳洲市场 宁德时代储能全场景解决方案亮相澳大利亚全能源展
    基于vue实现的资金管理系统(带权限)
    Lua语言编写爬虫程序
    java 泛型
    国产信创服务器如何进行安全可靠的文件传输?
    NEFU算法设计与分析课程设计
    ApplicationContext种类
  • 原文地址:https://blog.csdn.net/yeah_you_are/article/details/126203439