肮脏的标签侵蚀 [英] Scipy label erosion

查看:95
本文介绍了肮脏的标签侵蚀的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在numpy数组中的标记区域周围保持一圈像素?

How can I keep a ring of pixels around labeled regions in a numpy array?

在一个简单的情况下,我会减去腐蚀.当标签接触时,该方法不起作用.如何从A获取B?

In a simple case, I'd subtract the erosion. That approach doesn't work when the labels touch. How can I get get B from A?

A = array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
           [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
           [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
           [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
           [0, 0, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
           [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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

B = array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
           [0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0],
           [0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0],
           [0, 0, 2, 0, 0, 2, 2, 2, 2, 0, 0, 0],
           [0, 0, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
           [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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

我正在处理带有许多标签的大型阵列,因此每个标签上的单独腐蚀是不可行的.

I'm working with large arrays with many labels, so separate erosions on each label isn't an option.

推荐答案

新答案

实际上,我只是想到了一种更好的方法:

Actually, I just thought of a better way:

B = A * (np.abs(scipy.ndimage.laplace(A)) > 0)

作为一个完整的例子:

import numpy as np
import scipy.ndimage

A = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

B = A * (np.abs(scipy.ndimage.laplace(A)) > 0)

我认为这在所有情况下都应该有效(无论如何,对于带有A这样的标记"数组).

I think this should work in all cases (of "labeled" arrays like A, at any rate...).

如果您担心性能,可以将其分成几部分以减少内存开销:

If you're worried about performance, you can split this into a few pieces to reduce memory overhead:

B = scipy.ndimage.laplace(A)
B = np.abs(B, B) # Preform abs in-place
B /= B  # This will produce a divide by zero warning that you can safely ignore
B *= A  

此版本更为冗长,但应使用更少的内存.

This version is a lot more verbose, but should use much less memory.

旧答案

我想不出一种通常的scipy.ndimage函数一步一步实现的好方法. (我觉得高帽过滤器应该做您想要的,但是我不太清楚.)

I can't think of a good way to do it in one step with the usual scipy.ndimage functions. (I feel like a tophat filter should do what you want, but I can't quite figure it out.)

但是,正如您提到的,进行几次单独的腐蚀是一种选择.

However, doing several separate erosions is an option, as you mentioned.

如果使用find_objects提取每个标签的子区域,然后对子区域进行腐蚀,那么即使在非常大的阵列上,也应该可以获得合理的性能.

You should get reasonable performance even on very large arrays if you use find_objects to extract the subregion of each label, and then just do the erosion on the subregion.

例如:

import numpy as np
import scipy.ndimage

A = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

regions = scipy.ndimage.find_objects(A)

mask = np.zeros_like(A).astype(np.bool)

for val, region in enumerate(regions, start=1):
    if region is not None:
        subregion = A[region]
        mask[region] = scipy.ndimage.binary_erosion(subregion == val)

B = A.copy()
B[mask] = 0

这将产生:

array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
       [0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0],
       [0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0],
       [0, 0, 2, 0, 0, 2, 2, 2, 2, 0, 0, 0],
       [0, 0, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
       [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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

对于大型数组而言,性能应该是合理的,但这将很大程度上取决于不同标签对象跨越的区域大小以及您拥有标签对象的数量....

The performance should be reasonable for large arrays, but it's going to depend strongly on how large of an area the different labeled objects span and the number of labeled objects that you have....

这篇关于肮脏的标签侵蚀的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆