Jak wykryć obiekt na obrazach?

Potrzebuję rozwiązania Pythona.

Mam 40-60 zdjęć(zestaw Happy Holiday). Muszę wykryć obiekt na tych wszystkich obrazach.

Nie znam rozmiaru obiektu, formy, lokalizacji na obrazku, nie mam żadnego szablonu obiektu. Wiem tylko jedno: ten obiekt jest obecny na prawie wszystkich obrazach. Nazwałem go UFO.

Przykład: Tutaj wpisz opis obrazkaTutaj wpisz opis obrazkaTutaj wpisz opis obrazkaTutaj wpisz opis obrazka

Jak widać na przykładzie, od obrazu do obrazu wszystko się zmienia z wyjątkiem UFO. Po wykryciu muszę dostać:

Współrzędna X lewy górny róg

Współrzędna Y lewego górnego rogu

Szerokość niebieskiego obszaru obiektu (zaznaczam region na przykładzie jako czerwony prostokąt)

Wysokość obszaru obiektu niebieskiego

Author: Alex, 2013-02-08

2 answers

Gdy masz dane obrazu jako tablicę, możesz użyć wbudowanej funkcji numpy, aby to zrobić łatwo i szybko:

import numpy as np
import PIL

image = PIL.Image.open("14767594_in.png")

image_data = np.asarray(image)
image_data_blue = image_data[:,:,2]

median_blue = np.median(image_data_blue)

non_empty_columns = np.where(image_data_blue.max(axis=0)>median_blue)[0]
non_empty_rows = np.where(image_data_blue.max(axis=1)>median_blue)[0]

boundingBox = (min(non_empty_rows), max(non_empty_rows), min(non_empty_columns), max(non_empty_columns))

print boundingBox

Dam ci, za pierwsze zdjęcie:

(78, 156, 27, 166)

Więc twoje pożądane dane to:

  • lewy górny róg to (x, y): (27, 78)
  • width: 166 - 27 = 139
  • wysokość: 156 - 78 = 78

Wybrałem, że "każdy piksel o wartości niebieskiej większej niż mediana wszystkich wartości niebieskich" należy do Twojego obiektu. Oczekuję, że to zadziała dla Ciebie; jeśli nie, spróbuj coś innego lub podać kilka przykładów, gdzie to nie działa.

Edycja Przerobiłem mój kod na bardziej ogólny. Ponieważ dwa zdjęcia, o tym samym kształcie-kolorze, nie są wystarczająco ogólne (jak wskazuje Twój komentarz) tworzę więcej próbek syntetycznie.

def create_sample_set(mask, N=36, shape_color=[0,0,1.,1.]):
    rv = np.ones((N, mask.shape[0], mask.shape[1], 4),dtype=np.float)
    mask = mask.astype(bool)
    for i in range(N):
        for j in range(3):
            current_color_layer = rv[i,:,:,j]
            current_color_layer[:,:] *= np.random.random()
            current_color_layer[mask] = np.ones((mask.sum())) * shape_color[j]
    return rv

Tutaj kolor kształtu jest regulowany. Dla każdego z N = 26 obrazów wybierany jest losowy kolor tła. Możliwe byłoby również umieszczenie szumu w tle, nie zmieniłoby to wynik.

Następnie przeczytałem twój przykładowy obraz, stworzyłem z niego maskę kształtu i użyłem jej do tworzenia przykładowych obrazów. Rysuję je na siatce.

# create set of sample image and plot them
image = PIL.Image.open("14767594_in.png")
image_data = np.asarray(image)
image_data_blue = image_data[:,:,2]
median_blue = np.median(image_data_blue)
sample_images = create_sample_set(image_data_blue>median_blue)
plt.figure(1)
for i in range(36):
    plt.subplot(6,6,i+1)
    plt.imshow(sample_images[i,...])
    plt.axis("off")
plt.subplots_adjust(0,0,1,1,0,0)

Niebieskie kształty

Dla innej wartości shape_color (parametr do create_sample_set(...)), może to wyglądać następująco:

Zielone kształty

Następnie ustalę zmienność na piksel, używając odchylenia standardowego. Jak powiedziałeś, obiekt znajduje się na (prawie) wszystkich obrazach w tej samej pozycji. Więc variabiliy w tych obrazach będzie niski, podczas gdy dla inne piksele, będzie znacznie wyższa.

# determine per-pixel variablility, std() over all images
variability = sample_images.std(axis=0).sum(axis=2)

# show image of these variabilities
plt.figure(2)
plt.imshow(variability, cmap=plt.cm.gray, interpolation="nearest", origin="lower")

Wreszcie, jak w moim pierwszym fragmencie kodu, określ obwiednię. Teraz podaję również jego fabułę.

# determine bounding box
mean_variability = variability.mean()
non_empty_columns = np.where(variability.min(axis=0)<mean_variability)[0]
non_empty_rows = np.where(variability.min(axis=1)<mean_variability)[0]
boundingBox = (min(non_empty_rows), max(non_empty_rows), min(non_empty_columns), max(non_empty_columns))

# plot and print boundingBox
bb = boundingBox
plt.plot([bb[2], bb[3], bb[3], bb[2], bb[2]],
         [bb[0], bb[0],bb[1], bb[1], bb[0]],
         "r-")
plt.xlim(0,variability.shape[1])
plt.ylim(variability.shape[0],0)

print boundingBox
plt.show()

BoundingBox i wyodrębniony kształt

To jest to. Mam nadzieję, że tym razem będzie wystarczająco ogólne.

Kompletny skrypt do kopiowania i wklejania:

import numpy as np
import PIL
import matplotlib.pyplot as plt


def create_sample_set(mask, N=36, shape_color=[0,0,1.,1.]):
    rv = np.ones((N, mask.shape[0], mask.shape[1], 4),dtype=np.float)
    mask = mask.astype(bool)
    for i in range(N):
        for j in range(3):
            current_color_layer = rv[i,:,:,j]
            current_color_layer[:,:] *= np.random.random()
            current_color_layer[mask] = np.ones((mask.sum())) * shape_color[j]
    return rv

# create set of sample image and plot them
image = PIL.Image.open("14767594_in.png")
image_data = np.asarray(image)
image_data_blue = image_data[:,:,2]
median_blue = np.median(image_data_blue)
sample_images = create_sample_set(image_data_blue>median_blue)
plt.figure(1)
for i in range(36):
    plt.subplot(6,6,i+1)
    plt.imshow(sample_images[i,...])
    plt.axis("off")
plt.subplots_adjust(0,0,1,1,0,0)

# determine per-pixel variablility, std() over all images
variability = sample_images.std(axis=0).sum(axis=2)

# show image of these variabilities
plt.figure(2)
plt.imshow(variability, cmap=plt.cm.gray, interpolation="nearest", origin="lower")

# determine bounding box
mean_variability = variability.mean()
non_empty_columns = np.where(variability.min(axis=0)<mean_variability)[0]
non_empty_rows = np.where(variability.min(axis=1)<mean_variability)[0]
boundingBox = (min(non_empty_rows), max(non_empty_rows), min(non_empty_columns), max(non_empty_columns))

# plot and print boundingBox
bb = boundingBox
plt.plot([bb[2], bb[3], bb[3], bb[2], bb[2]],
         [bb[0], bb[0],bb[1], bb[1], bb[0]],
         "r-")
plt.xlim(0,variability.shape[1])
plt.ylim(variability.shape[0],0)

print boundingBox
plt.show()
 26
Author: Thorsten Kranz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-11 07:54:36

Tworzę drugą odpowiedź zamiast rozszerzać moją pierwszą odpowiedź jeszcze bardziej. Stosuję to samo podejście, ale na nowych przykładach. Jedyną różnicą jest to, że używam zestawu ustalonych progów zamiast wyznaczania go automatycznie. Jeśli możesz się nim bawić, to powinno wystarczyć.

import numpy as np
import PIL
import matplotlib.pyplot as plt
import glob

filenames = glob.glob("14767594/*.jpg")
images = [np.asarray(PIL.Image.open(fn)) for fn in filenames]
sample_images = np.concatenate([image.reshape(1,image.shape[0], image.shape[1],image.shape[2]) 
                            for image in images], axis=0)

plt.figure(1)
for i in range(sample_images.shape[0]):
    plt.subplot(2,2,i+1)
    plt.imshow(sample_images[i,...])
    plt.axis("off")
plt.subplots_adjust(0,0,1,1,0,0)

# determine per-pixel variablility, std() over all images
variability = sample_images.std(axis=0).sum(axis=2)

# show image of these variabilities
plt.figure(2)
plt.imshow(variability, cmap=plt.cm.gray, interpolation="nearest", origin="lower")

# determine bounding box
thresholds = [5,10,20]
colors = ["r","b","g"]
for threshold, color in zip(thresholds, colors): #variability.mean()
    non_empty_columns = np.where(variability.min(axis=0)<threshold)[0]
    non_empty_rows = np.where(variability.min(axis=1)<threshold)[0]
    boundingBox = (min(non_empty_rows), max(non_empty_rows), min(non_empty_columns), max(non_empty_columns))

    # plot and print boundingBox
    bb = boundingBox
    plt.plot([bb[2], bb[3], bb[3], bb[2], bb[2]],
             [bb[0], bb[0],bb[1], bb[1], bb[0]],
             "%s-"%![enter image description here][1]color, 
             label="threshold %s" % threshold)
    print boundingBox

plt.xlim(0,variability.shape[1])
plt.ylim(variability.shape[0],0)
plt.legend()

plt.show()

Produkowane działki:

Obrazy wejścioweWyniki

Twoje wymagania są ściśle związane z ERP w neurologii poznawczej. Im więcej obrazów wejściowych masz, tym lepsze będzie to podejście wraz ze wzrostem stosunku sygnału do szumu.
 9
Author: Thorsten Kranz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-13 14:48:40