我需要python解决方案。
我有40-60张图片(Happy Holiday set)。我需要检测所有这些图像上的对象。
我不知道对象大小,形式,图像上的位置,我没有任何对象模板。我只知道一件事:这个物体几乎存在于所有图像中。我称它为UFO。
实施例:
如示例所示,从图像到图像,除了UFO之外,一切都会发生变化。检测后我需要得到:
左上角的X坐标
左上角的Y坐标
蓝色物体区域的宽度(我将示例区域标记为红色矩形)
蓝色物体区域的高度
答案 0 :(得分:27)
当您将图像数据作为数组时,您可以使用内置的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)
所以你想要的数据是:
(27, 78)
166 - 27 = 139
156 - 78 = 78
我选择了#34;每个像素的蓝色值都大于所有蓝色值的中位数"属于你的对象。我希望这对你有用;如果没有,请尝试别的或提供一些不起作用的例子。
修改强> 我重新编写了我的代码以使其更加通用。由于两个具有相同形状颜色的图像不够通用(正如您的评论所示),我会综合创建更多样本。
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()
那就是它。我希望这次足够普遍。
完整的复制和粘贴脚本:
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()
答案 1 :(得分:9)
我创建了第二个答案,而不是更多地扩展我的第一个答案。我使用相同的方法,但在你的新例子。唯一的区别是:我使用一组固定阈值而不是自动确定它。如果你可以玩它,这应该足够了。
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()
制作地块:
您的要求与认知神经科学中的ERP密切相关。您拥有的输入图像越多,随着信噪比的增加,此方法的效果就越好。