Ответ 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)
Для другого значения shape_color
(параметр create_sample_set(...)
) это может выглядеть так:
Далее я определю переменную пикселя при стандартном отклонении. Как вы сказали, объект находится на (почти) всех изображениях в одном и том же положении. Таким образом, переменная в этих изображениях будет низкой, а для других пикселей она будет значительно выше.
# 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()
Что это. Надеюсь, на этот раз достаточно общего.
Заполните 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()