1

Я ищу надежный способ извлечь передний план из изображения, где фон имеет некоторый шум в нем.Извлечение изображения переднего плана в качестве маски по пороговому значению

Таким образом, изображение, которое я хочу использовать его на это:

Image with some background noise

Моя попытка была использовать Otsu thresholding. Я делал это в Python следующим образом:

from skimage.filter import threshold_otsu 
import os.path as path 
import matplotlib.pyplot as plt 

img = io.imread(path.expanduser('~/Desktop/62.jpg')) 
r_t = threshold_otsu(img[:, :, 0]) 
g_t = threshold_otsu(img[:, :, 1]) 
b_t = threshold_otsu(img[:, :, 2]) 

m = np.zeros((img.shape[0], img.shape[1]), dtype=np.uint8) 
mask = (img[:, :, 0] < r_t) & (img[:, :, 1] < g_t) & (img[:, :, 2] < b_t) 
m[~mask] = 255 

plt.imshow(m) 
plt.show() 

Это дает R, G, B порог, как (62 67 64), который является немного высока. Результат:

Otsu result

Это изображение является также один из снимков, где Otsu thresholding работали лучше. Если я использую ручной порог как значение 30, он работает достаточно хорошо. Результат:

Manual

мне было интересно, если есть некоторые другие подходы, которые я должен попробовать. Сегментация действительно не моя область знаний, и то, что я могу сделать из коробки, кажется ограниченным.

ответ

2

Ваше изображение выглядит не очень ярким. Таким образом, вы можете выполнить сегментацию по серым значениям, а не по каждому цвету отдельно, а затем объединить три маски.

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

Пример:

import numpy as np 
import skimage.io as io 
import skimage.filter as filter 
import matplotlib.pyplot as plt 

img = io.imread('62.jpg') 
gray = np.sum(img, axis=2) # summed up over red, green, blue 
#threshold = filter.threshold_otsu(gray) # delivers very high threshold 
threshold = filter.threshold_isodata(gray) # works extremely well 
#threshold = filter.threshold_yen(gray) # delivers even higher threshold 
print(threshold) 

plt.imshow(gray > threshold) 
plt.show() 

дает:

enter image description here

+0

Это довольно хорошо. Я попробую с некоторыми другими изображениями и посмотрю, насколько он прочен. – Luca

+1

@Luca, если у вас есть другие изображения, а некоторые не работают, просто выберите худшие три или около того и спросите еще раз (я бы предпочел в новом вопросе). – Trilarion

+0

Спасибо Trillion. Это очень любезно с вашей стороны. Я буду. У меня такое чувство, что я могу заставить его работать сейчас – Luca

Смежные вопросы