【问题标题】:Finding blank regions in image查找图像中的空白区域
【发布时间】:2011-03-19 15:34:41
【问题描述】:

这个问题在某种程度上与语言无关,但我选择的工具恰好是一个 numpy 数组。

我正在做的是通过 PIL 获取两个图像的差异:

img = ImageChops.difference(img1, img2)

我想找到包含从一张图片到另一张图片变化的矩形区域。当然有内置的.getbbox() 方法,但是如果有两个区域发生变化,它将从一个区域返回一个框到另一个区域,如果每个角落只有1个像素变化,它将返回整个图像。

例如,考虑以下情况,其中o 是一个非零像素:

______________________
|o            ooo    |
|      oooo   ooo    |
|      o             |
|      o  o          |
|                    |
|     oo       o     |
|    o  o     ooo    |
|     oo     ooooo   |
|             ooo    |
|              o     |
|____________________|

我想获得 4x4 元组,其中包含每个非零区域的边界框。对于

的边缘情况
oooo
o
o  o

结构,我并不十分担心如何处理 - 将两个部分分开或放在一起,因为倒 L 形的边界将完全与单个像素的边界重叠。

我从未在图像处理方面做过如此先进的事情,所以我想在真正写任何东西之前获得一些输入(如果我已经在使用的模块中有预先存在的方法,我欢迎他们!)。

我的伪代码版本是这样的:

for line in image:
   started = False
   for pixel in line:
      if pixel and not started:
         started = True
         save start coords
      elif started and not pixel:
         started = False
         save end coords (x - 1 of course)

这应该给我一个坐标列表,但是我必须确定这些区域是否是连续的。我可以通过图形类型的搜索来做到这一点吗? (上学期我们在算法中做了很多 DFS 和 BFS)当然我想我可以代替/结合我以前的循环来做?

我不会在“大”图像上执行此操作 - 它们是从网络摄像头中提取的,而我目前拥有的最好的图像是 640x480。最多我会做 720p 或 1080p,但这对于未来来说已经足够远了,这不是一个真正的问题。

所以我的问题是:我是走在正确的道路上,还是偏离了方向?更重要的是,是否有任何内置功能阻止我重新发明轮子?最后,是否有任何我应该查看的好资源(教程、论文等)对这里有所帮助?

谢谢!

【问题讨论】:

    标签: python language-agnostic image-processing numpy python-imaging-library


    【解决方案1】:

    您可以在图像中查找连接的组件,然后确定这些组件的边界框。

    【讨论】:

    • 我很困惑 - 这与我说的我在做什么有什么不同?
    【解决方案2】:

    一个聚类包 (ie this) 应该能够完成大部分工作(查找连接的像素)。找到一个集群的边界框就很简单了。

    【讨论】:

    • 集群如何帮助(尤其是这个包)?从我收集阅读文档字符串的内容来看,它只能找到 X 距离之外的数据,并且(似乎)不存储任何 X-Y 数据。我错过了什么吗?
    【解决方案3】:

    我相信scipy's ndimage module 拥有你所需要的一切......

    这是一个简单的例子

    import numpy as np
    import scipy as sp
    import scipy.ndimage.morphology
    
    # The array you gave above
    data = np.array( 
            [
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 
               [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 
               [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
               [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
               [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
               [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 
               [0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 
               [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], 
               [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 
               [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 
            ])
    
    
    # Fill holes to make sure we get nice clusters
    filled = sp.ndimage.morphology.binary_fill_holes(data)
    
    # Now seperate each group of contigous ones into a distinct value
    # This will be an array of values from 1 - num_objects, with zeros
    # outside of any contigous object
    objects, num_objects = sp.ndimage.label(filled)
    
    # Now return a list of slices around each object
    #  (This is effectively the tuple that you wanted)
    object_slices =  sp.ndimage.find_objects(objects)
    
    # Just to illustrate using the object_slices
    for obj_slice in object_slices:
        print data[obj_slice]
    

    这个输出:

    [[1]]
    [[1 1 1]
     [1 1 1]]
    [[1 1 1 1]
     [1 0 0 0]
     [1 0 0 1]]
    [[1]]
    [[0 1 1 0]
     [1 0 0 1]
     [0 1 1 0]]
    [[0 0 1 0 0]
     [0 1 1 1 0]
     [1 1 1 1 1]
     [0 1 1 1 0]
     [0 0 1 0 0]]
    

    请注意,“object_slices”基本上是您最初要求的,如果您需要实际的索引。

    编辑:只是想指出,尽管它似乎可以正确处理

    的边缘情况
    [[1 1 1 1]
     [1 0 0 0]
     [1 0 0 1]]
    

    它实际上没有(因此额外的孤独 [[1]])。如果您打印出“对象”数组并查看对象 3 和 4,您可以看到这一点。

    [[1 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0]
     [0 0 0 0 0 0 3 3 3 3 0 0 0 2 2 2 0 0 0 0]
     [0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 3 0 0 4 0 0 0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     [0 0 0 0 0 5 5 0 0 0 0 0 0 0 6 0 0 0 0 0]
     [0 0 0 0 5 5 5 5 0 0 0 0 0 6 6 6 0 0 0 0]
     [0 0 0 0 0 5 5 0 0 0 0 0 6 6 6 6 6 0 0 0]
     [0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 0 0 0 0]
     [0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0]]
    

    希望有帮助!

    [1]

    【讨论】:

    • 圣洁的烟太完美了!这正是我想要的——而且我认为我实际上更喜欢它以这种方式处理边缘情况——这样它真的会得到 all 像素的框。我希望我能多次投票!
    • @Wayne - 很高兴为您提供帮助!一旦你学会了如何将各种运算符串在一起,scipy.ndimage 中有相当多的函数。祝你好运!
    • @JoeKington 是最有帮助的程序员之一
    • @chimpsarehungry - 谢谢!很高兴为您提供帮助!
    • 我知道这是错误的data[np.where(max(np.sum(obj_slice))] .. 但是有没有办法只打印最大的对象?
    猜你喜欢
    • 2010-09-17
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    • 2012-02-22
    • 2013-05-11
    • 1970-01-01
    • 2021-03-21
    • 1970-01-01
    相关资源
    最近更新 更多