【问题标题】:Count the number of "holes" in a bitmap计算位图中“孔”的数量
【发布时间】:2010-10-26 16:56:39
【问题描述】:

考虑一个 MxN 位图,其中单元格为 0 或 1。“1”表示填充,“0”表示空。

查找位图中“孔”的数量,其中孔是空单元的连续区域。

例如,这有两个孔:

11111  
10101  
10101  
11111  

...这只有一个:

11111  
10001  
10101  
11111

当 M 和 N 都在 1 和 8 之间时,最快的方法是什么?

澄清:对角线不被认为是连续的,只有边相邻很重要。

注意:我正在寻找利用数据格式的东西。我知道如何将其转换为图表并 [BD] FS 它,但这似乎有点过头了。

【问题讨论】:

  • 为什么会有这种家庭作业或代码高尔夫的味道? @Florin,感谢您的更新。请考虑此评论“已撤销”。我们会相信你的话。
  • 它尝起来像家庭作业!
  • 这不是功课,但没关系。我正在尝试解决一个更大的问题,而这只是一个子问题。
  • 孔是否仅正交连接?还是也允许诊断?
  • 我同意你在这方面需要图论。

标签: algorithm image-processing computer-vision maze


【解决方案1】:

你需要在你的图片上做connected component labeling。您可以使用我上面链接的维基百科文章中描述的Two-pass algorithm。鉴于您的问题规模较小,One-pass algorithm 可能就足够了。

您也可以使用BFS/DFS,但我推荐上述算法。

【讨论】:

  • 是的,连接组件标签应该可以解决问题。另外,恭喜 10k,@Jacob(或者几乎 - 我猜你今天达到了代表上限)。
  • @Jonas:我知道!希望弗洛林今天会接受这个答案:)
  • @Jonas:我现在可以承认恭喜了:D
  • 我稍微改变了两次算法,但主要思想是gist.github.com/atonamy/3c50f63aebdecc9b881756e889fb5278 如果解决方案看起来可以接受编码面试,请给你的 cmets
【解决方案2】:

这似乎是对不相交集数据结构的一个很好的使用。
将位图转换为二维数组
循环遍历每个元素
如果当前元素为 0,则将其与其“前一个”空邻居(已访问)的集合合并
如果它没有空邻居,则将其添加到自己的集合中

然后只计算组数

【讨论】:

  • 我在看他之前写了这个答案。
【解决方案3】:

使用表查找和按位运算可能会获得一些优势。

例如可以在 256 个元素的表中查找 8 像素的整行,因此通过单次查找获得字段 1xN 中的孔数。然后可能会有一些 256xK 元素的查找表,其中 K 是前一行的孔配置数,包含完整孔数和下一个孔配置。这只是一个想法。

【讨论】:

  • 我刚开始构建我的 2^64 查找表,但是我用完了 RAM 8^) 的当年预算
  • florin:使用分布式计算! =)
  • 我发现这个谜题很有趣,我花了一些空闲时间用查找和按位运算绘制了“逐行”算法的草图,只使用了 560 字节的表(对于 8 位宽的模式) .这是代码:dl.dropbox.com/u/13343791/holecount2.c 抱歉,如果代码没有很好的记录。
【解决方案4】:

function BitmapHoles(strArr) { 
    let returnArry = [];
    let indexOfZ = [];
    let subarr;
     for(let i=0 ; i < strArr.length; i++){
       subarr = strArr[i].split("");
      let index = [];
      for(let y=0 ; y < subarr.length; y++){
        if(subarr[y] == 0)
        index.push(y);
        if(y == subarr.length-1)
        indexOfZ.push(index);
      }
    }
    for(let i=0 ; i < indexOfZ.length; i++){
        for(let j=0; j<indexOfZ[i].length ; j++){
          if(indexOfZ[i+1] && (indexOfZ[i][j]==indexOfZ[i+1][j] || indexOfZ[i+1].indexOf(indexOfZ[i][j])))
          returnArry.indexOf(strArr[i]) < 0 ? returnArry.push(strArr[i]): false;
          if(Math.abs(indexOfZ[i][j]-indexOfZ[i][j+1])==1)
          returnArry.indexOf(strArr[i]) < 0 ? returnArry.push(strArr[i]): false;
        }
    }
    
      return returnArry.length; 
    
    }
       
    // keep this function call here 
    console.log(BitmapHoles(readline()));

【讨论】:

    【解决方案5】:

    我在Mediumhttps://medium.com/@ahmed.wael888/bitmap-holes-count-using-typescript-javascript-387b51dd754a写了一篇文章描述了答案

    但这里是代码,逻辑不复杂,不看文章也能看懂。

    export class CountBitMapHoles {
        bitMapArr: number[][];
        holesArr: Hole[] = [];
        maxRows: number;
        maxCols: number;
    
        constructor(bitMapArr: string[] | number[][]) {
            if (typeof bitMapArr[0] == 'string') {
                this.bitMapArr = (bitMapArr as string[]).map(
                    (word: string): number[] => word.split('').map((bit: string): number => +bit))
            } else {
                this.bitMapArr = bitMapArr as number[][]
            }
            this.maxRows = this.bitMapArr.length;
            this.maxCols = this.bitMapArr[0].length;
        }
    
        moveToDirection(direction: Direction, currentPosition: number[]) {
            switch (direction) {
                case Direction.up:
                    return [currentPosition[0] - 1, currentPosition[1]]
    
                case Direction.down:
                    return [currentPosition[0] + 1, currentPosition[1]]
    
                case Direction.right:
                    return [currentPosition[0], currentPosition[1] + 1]
    
                case Direction.left:
                    return [currentPosition[0], currentPosition[1] - 1]
    
            }
        }
        reverseDirection(direction: Direction) {
            switch (direction) {
                case Direction.up:
                    return Direction.down;
                case Direction.down:
                    return Direction.up
                case Direction.right:
                    return Direction.left
                case Direction.left:
                    return Direction.right
            }
        }
        findNeighbor(parentDir: Direction, currentPosition: number[]) {
            let directions: Direction[] = []
            if (parentDir === Direction.root) {
                directions = this.returnAvailableDirections(currentPosition);
            } else {
                this.holesArr[this.holesArr.length - 1].positions.push(currentPosition)
                directions = this.returnAvailableDirections(currentPosition).filter((direction) => direction != parentDir);
            }
            directions.forEach((direction) => {
                const childPosition = this.moveToDirection(direction, currentPosition)
                if (this.bitMapArr[childPosition[0]][childPosition[1]] === 0 && !this.checkIfCurrentPositionExist(childPosition)) {
                    this.findNeighbor(this.reverseDirection(direction), childPosition)
                }
            });
            return
        }
        returnAvailableDirections(currentPosition: number[]): Direction[] {
            if (currentPosition[0] == 0 && currentPosition[1] == 0) {
                return [Direction.right, Direction.down]
            } else if (currentPosition[0] == 0 && currentPosition[1] == this.maxCols - 1) {
                return [Direction.down, Direction.left]
            } else if (currentPosition[0] == this.maxRows - 1 && currentPosition[1] == this.maxCols - 1) {
                return [Direction.left, Direction.up]
            } else if (currentPosition[0] == this.maxRows - 1 && currentPosition[1] == 0) {
                return [Direction.up, Direction.right]
            } else if (currentPosition[1] == this.maxCols - 1) {
                return [Direction.down, Direction.left, Direction.up]
            } else if (currentPosition[0] == this.maxRows - 1) {
                return [Direction.left, Direction.up, Direction.right]
            } else if (currentPosition[1] == 0) {
                return [Direction.up, Direction.right, Direction.down]
            } else if (currentPosition[0] == 0) {
                return [Direction.right, Direction.down, Direction.left]
            } else {
                return [Direction.right, Direction.down, Direction.left, Direction.up]
            }
        }
        checkIfCurrentPositionExist(currentPosition: number[]): boolean {
            let found = false;
            return this.holesArr.some((hole) => {
                const foundPosition = hole.positions.find(
                    (position) => (position[0] == currentPosition[0] && position[1] == currentPosition[1]));
                if (foundPosition) {
                    found = true;
                }
                return found;
            })
    
        }
    
        exec() {
            this.bitMapArr.forEach((row, rowIndex) => {
                row.forEach((bit, colIndex) => {
                    if (bit === 0) {
                        const currentPosition = [rowIndex, colIndex];
                        if (!this.checkIfCurrentPositionExist(currentPosition)) {
                            this.holesArr.push({
                                holeNumber: this.holesArr.length + 1,
                                positions: [currentPosition]
                            });
                            this.findNeighbor(Direction.root, currentPosition);
                        }
                    }
                });
            });
            console.log(this.holesArr.length)
            this.holesArr.forEach(hole => {
                console.log(hole.positions)
            });
            return this.holesArr.length
        }
    }
    enum Direction {
        up = 'up',
        down = 'down',
        right = 'right',
        left = 'left',
        root = 'root'
    }
    
    interface Hole {
        holeNumber: number;
        positions: number[][]
    }
    

    main.ts 文件

    import {CountBitMapHoles} from './bitmap-holes'
    
    const line = ['1010111', '1001011', '0001101', '1111001', '0101011']
    function main() {
        const countBitMapHoles = new CountBitMapHoles(line)
        countBitMapHoles.exec()
    }
    
    main()
    

    【讨论】:

      猜你喜欢
      • 2011-08-19
      • 2020-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多