Извличане на изображение на преден план като маска чрез прагове

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

И така, изображението, върху което искам да го използвам, е:

Изображение с някакъв фонов шум

Моят опит беше да използвам 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 резултат

Това изображение също е едно от изображенията, при които Otsu thresholding работи най-добре. Ако използвам ръчен праг като стойност 30, той работи доста добре. Резултатът е:

Ръководство

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


person Luca    schedule 03.02.2015    source източник


Отговори (1)


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

Разглеждайки пакета scikit-image.filter, има няколко други прагови метода. Опитах ги всичките и открих, че threshold_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()

дава:

въведете описание на изображението тук

person Trilarion    schedule 03.02.2015
comment
Това е доста добре. Ще опитам с някои други изображения и ще видя колко здрав може да бъде. - person Luca; 03.02.2015
comment
@Luca, ако имате други изображения и някои не работят, просто изберете най-лошите три или така и попитайте отново (бих предпочел в нов въпрос). - person Trilarion; 03.02.2015
comment
Благодаря Трилион. Това е много мило от твоя страна. Аз ще. Имам чувството, че мога да го накарам да работи сега - person Luca; 03.02.2015