Как убрать шум на границе без потери данных в середине маски - PullRequest
3 голосов
/ 07 февраля 2020

Я пытаюсь отделить пятна ткани от изображения. Я сделал некоторую начальную предварительную обработку и получил следующий результат. Меня беспокоит шум на границах. Если я разрушу горизонтальное / вертикальное ядро, я потеряю некоторые данные в середине. Я не уверен, что лучше достичь результатов, или я должен go с помощью другого подхода к сегментации.

Вот пример изображения:

image

import numpy as np 
import os
import matplotlib.pyplot as plt
from skimage import io
from skimage.filters import threshold_mean
from skimage.exposure import adjust_sigmoid, adjust_gamma
from skimage.morphology import opening
from skimage import morphology
import scipy.ndimage as ndi

def create_binary_mask(path_to_file):
    file = io.imread(path_to_file)

    #APPLY FILTERS FOR BETTER THRESHOLD
    img_med = ndi.median_filter(file, size=20) #REDUCE NOISE
    adjusted_gamma = adjust_gamma(img_med, 1.8, 2) #INCREASE GAMMA
    adjusted_sigmoid = adjust_sigmoid(adjusted_gamma, 0.01) #INCREASE CONTRAST

    #DO THE MEAN THRESHOLD
    thresh = threshold_mean(adjusted_sigmoid)
    binary = adjusted_sigmoid > thresh

    #REMOVE SMALL NOISE WITHIN THE IMAGE
    disk = morphology.disk(radius=7)
    opening = morphology.binary_opening(binary, disk)

    fig, axis = plt.subplots(1,4, figsize=(10,10))
    axis[0].imshow(file, cmap='gray')
    axis[0].set_title('Original File')
    axis[1].imshow(adjusted_sigmoid, cmap='gray')
    axis[1].set_title('Adjusted Sigmoid')
    axis[2].imshow(binary, cmap='gray')
    axis[2].set_title('Mean Threshold')
    axis[3].imshow(opening, cmap='gray')
    axis[3].set_title('After opening')
    plt.savefig('results.png')
    plt.show()


path_to_file = "sample_img.png"
create_binary_mask(path_to_file)

Results

Ответы [ 2 ]

1 голос
/ 10 февраля 2020

Может быть полезно использовать операторы атрибутов, в частности skimage.morphology.diameter_opening, для удаления длинных линий, оставляя объекты меньшего радиуса нетронутыми. Подробности см. В этом примере:

https://scikit-image.org/docs/dev/auto_examples/filters/plot_attribute_operators.html

Подробное объяснение того, как работает этот метод, можно найти здесь:

https://scikit-image.org/docs/dev/auto_examples/developers/plot_max_tree.html

0 голосов
/ 08 февраля 2020

Простой подход состоит в том, чтобы выполнить морфологическое закрытие двоичного изображения, чтобы соединить шум вместе в единый контур. Отсюда мы можем найти контуры и фильтр, используя область контура. Мы можем эффективно убрать шум на границе, рисуя контур. Вот результат с шумом, окрашенным в цвет фона. Если вы хотите снять маску, просто закрасьте ее черным (0,0,0).

image

import cv2
import numpy as np

# Load image, grayscale, Gaussian blur, adaptive threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (7,7), 0)
thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,61,5)

# Morph close to connect noise
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=5)

# Filter using contour area and fill in contour to remove noise
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area > 250000:
        cv2.drawContours(image, [c], -1, (43,43,43), -1)

cv2.imwrite('image.png', image)
cv2.waitKey()
...