шумоизолировать сегментацию изображения (режим фильтрации?) - или как векторизовать эту операцию в numpy? - PullRequest
0 голосов
/ 25 мая 2020

ОБНОВЛЕНИЕ: В моем первоначальном посте я тупо применил stats.mode патчем, а не вдоль оси патчей. Исправление этого увеличило мою скорость в 4 раза, однако это все еще медленное, и мои первоначальные вопросы все еще существуют: (1) могу ли я увеличить скорость? (2) существуют ли другие / лучшие / стандартные подходы к очистке зашумленных категориальных данных? Верните сообщение:

У меня есть несколько шумных результатов сегментации изображений, и я хочу их очистить. Моя идея заключалась в том, чтобы взять значение режима для (3,3) патчей. Этот код работает, но он слишком медленный.:

from sklearn.feature_extraction import image
from scipy import stats

def _mode(a,axis=None):
    m,_=stats.mode(a,axis=axis)
    return m   

def mode_smoothing(data,kernel=(3,3)):
    patches=image.extract_patches_2d(data,kernel)
    nb_patches=patches.shape[0]
    patches=patches.reshape(nb_patches,-1)
    return _mode(patches,1).reshape(int(np.sqrt(nb_patches)),-1)


""" original method (new version is ~ 5 times faster, but still slow)
def _mode(arr):
    m,_=stats.mode(arr,axis=None)
    return m   

def mode_smoothing(data,kernel=(3,3)):
    patches=image.extract_patches_2d(data,kernel)
    nb_patches=patches.shape[0]
    w=int(np.sqrt(nb_patches))
    o=np.array([_mode(patches[p]) for p in range(nb_patches)])
    return o.reshape(w,-1)
"""

Вопросы:

  1. Есть ли способ сделать это намного быстрее? исключить цикл / векторизация в numpy? перенос на c напрямую или с помощью numba et c? Я изо всех сил пытался заставить что-то работать по этим путям
  2. Существуют ли лучшие / более стандартные методы для выполнения шумоподавления, подобного этому, для категориальных данных изображения?

Вот пример до / после из mode_smoothing метод выше

noisy segmentation after mode filter

1 Ответ

0 голосов
/ 26 мая 2020

Ниже я представляю 2 ответа на свой вопрос:

  1. путем расширения моей первоначальной попытки до функции, которую numba может обрабатывать
  2. , используя приведенное выше предложение Alex Alex , который я назову «категориальным сглаживанием» (есть ли стандартное название для этого метода?)

Я еще не выписал математического доказательства, но похоже, что этот патч Поразрядное сглаживание эквивалентно категориальному сглаживанию для правильного выбора параметров. Оба приводят к значительному увеличению скорости, но решение категориального сглаживания чище, быстрее и не требует numba - поэтому оно выигрывает.


NUMBA

@njit
def mode_smoothing(data,kernel=(3,3),step=(1,1),edges=False,high_value=False,center_boost=False):
    """ mode smoothing over patches

    Args:
        data<np.array>: numpy array (ndim=2)
        kernel<tuple[int]>: (height,width) of patch window
        step<tuple[int]>: (y-step,x-step)
        edges<bool>: 
            - if true 
                * include edge patches by taking mode over smaller patch window 
                * the returned image be the same shape as the input data
            - if false
                * only run over patches with the full kernel size
                * the returned image will be reduced in size by the radius of the kernel
        high_value<bool>: 
            when there are multiple possible mode values choose the highest if true, 
            otherwise choose the lowest value
        center_boost<int|bool>: 
            if true, instead of using pure mode-value increase the count on the center pixel
    Return
        <np.array> of patch wise mode values. shape my be different than input. see `edges` above
    """
    h,w=data.shape
    ry=int(kernel[0]//2)
    rx=int(kernel[1]//2)
    sy,sx=step

    _mode_vals=[]

    if edges:
        j0,j1=0,h
        i0,i1=0,w
    else:
        j0,j1=ry,h-ry
        i0,i1=rx,w-rx

    for j in range(j0,j1,sy):
        for i in range(i0,i1,sx):

            ap=data[
                max(j-ry,0):j+ry+1,
                max(i-rx,0):i+rx+1]

            cv=data[j,i]

            values=np.unique(ap)
            count=0
            for v in values:
                newcount=(ap==v).sum()
                if center_boost and (v==cv):
                    newcount+=center_boost
                if high_value:
                    test=newcount>=count
                else:
                    test=newcount>count
                if test:
                    count=newcount
                    mode_value=v     
            _mode_vals.append(mode_value)

    return np.array(_mode_vals).reshape(j1-j0,i1-i0)

КАТЕГОРИЧЕСКОЕ Сглаживание

from scipy.signal import convolve2d
KERNEL=np.ones((3,3))

def categorical_smoothing(data,nb_categories,kernel=KERNEL):
    data=np.eye(nb_categories)[:,data]
    for i in range(nb_categories):
        data[i]=convolve2d(data[i],kernel,mode='same')
    return data.argmax(axis=0)

ЭКВИВАЛЕНТНОСТЬ / ПРОВЕРКА СКОРОСТИ

Это, вероятно, легко доказать, но ...

S=512
N=19
data=np.random.randint(0,N,(S,S))
%time o1=mode_smoothing(data,edges=True,center_boost=False)
kernel=np.ones((3,3))
%time o2=categorical_smoothing(data,N,kernel=kernel)
print((o1==o2).all())
print()
data=np.random.randint(0,N,(S,S))
%time o1=mode_smoothing(data,edges=True,center_boost=1)
kernel=np.ones((3,3))
kernel[1,1]=2
%time o2=categorical_smoothing(data,N,kernel=kernel)
print((o1==o2).all())

""" OUTPUT
CPU times: user 826 ms, sys: 0 ns, total: 826 ms
Wall time: 825 ms
CPU times: user 416 ms, sys: 7.83 ms, total: 423 ms
Wall time: 423 ms
True

CPU times: user 825 ms, sys: 3.78 ms, total: 829 ms
Wall time: 828 ms
CPU times: user 422 ms, sys: 3.91 ms, total: 426 ms
Wall time: 425 ms
True
"""
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...