Как определить объект на изображения? - программирование
Подтвердить что ты не робот

Как определить объект на изображения?

Мне нужно решение python.

У меня есть 40-60 изображений (Happy Holiday set). Мне нужно обнаружить объект на всех этих изображениях.

Я не знаю размер объекта, форму, местоположение на изображении, у меня нет объектного шаблона. Я знаю только одно: этот объект присутствует почти во всех изображениях. Я назвал его НЛО.

Пример: enter image description hereenter image description hereenter image description hereenter image description here

Как видно из примера, из изображения в изображение все изменяется, кроме НЛО. После обнаружения мне нужно получить:

Координата X верхнего левого угла

Координата Y верхнего левого угла

ширина области голубого объекта (i отмеченная область в качестве красного прямоугольника)

высота области голубого объекта

4b9b3361

Ответ 1

Когда у вас есть данные изображения как массив, вы можете использовать встроенную функцию numpy для этого легко и быстро:

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

даст вам, для первого изображения:

(78, 156, 27, 166)

Итак, ваши желаемые данные:

  • верхний левый угол (x, y): (27, 78)
  • width: 166 - 27 = 139
  • высота: 156 - 78 = 78

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

ИЗМЕНИТЬ Я переработал свой код, чтобы быть более общим. Поскольку два изображения с одинаковым цветом формы не являются достаточно общими (как указывает ваш комментарий), я создаю больше образцов синтетически.

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

Здесь цвет формы регулируется. Для каждого из изображений N = 26 выбирается случайный цвет фона. Также возможно поставить шум в фоновом режиме, это не изменит результат.

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

# 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)

Blue shapes

Для другого значения shape_color (параметр create_sample_set(...)) это может выглядеть так:

Green shapes

Далее я определю переменную пикселя при стандартном отклонении. Как вы сказали, объект находится на (почти) всех изображениях в одном и том же положении. Таким образом, переменная в этих изображениях будет низкой, а для других пикселей она будет значительно выше.

# 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()

BoundingBox and extracted shape

Что это. Надеюсь, на этот раз достаточно общего.

Заполните script для копирования и вставки:

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()

Ответ 2

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

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()

Произведенные графики:

Input imagesOutputs

Ваши требования тесно связаны с ERP в когнитивной нейронауке. Чем больше входных изображений у вас есть, тем лучше этот подход будет работать по мере увеличения отношения сигнал/шум.