python - 有没有办法使用 numpy 或 opencv 对图像进行切片,以使切片图像具有至少一个感兴趣对象的实例?
问题描述
本质上,我的原始图像具有某个对象的 N 个实例。我在一个文本文件中有边界框坐标和所有它们的类。这基本上是 YoloV3 和暗网的数据集。我想通过对原始图像进行切片来生成其他图像,使其包含这些对象之一的至少一个实例,如果包含,则保存图像以及该图像中对象的新边界框坐标。
以下是对图像进行切片的代码:
x1 = random.randint(0, 1200)
width = random.randint(0, 800)
y1 = random.randint(0, 1200)
height = random.randint(30, 800)
slice_img = img[x1:x1+width, y1:y1+height]
plt.imshow(slice_img)
plt.show()
我的下一步是使用模板匹配来查找我的切片图像是否在原始图像中:
w, h = slice_img.shape[:-1]
res = cv2.matchTemplate(img, slice_img, cv2.TM_CCOEFF_NORMED)
threshold = 0.6
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]): # Switch columns and rows
cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 5)
cv2.imwrite('result.png', img)
在这个阶段,我很迷茫,不知道如何继续前进。最终,我需要许多带有相应文本文件的新图像,其中包含类和坐标。任何意见,将不胜感激。谢谢你。
PS 很遗憾,我无法与您分享我的图片。
解决方案
模板匹配对此太过分了。模板匹配本质上是在您的主图像上滑动一个内核图像并比较每个像素,执行许多计算。无需搜索图像,因为您已经知道对象在图像中的位置。本质上,您正在尝试确定一个矩形(对象的边界框)是否与切片充分重叠,并且您知道每个矩形的确切坐标。因此,这是一个几何问题而不是计算机视觉问题。
(顺便说一句:您所说的切片的正确术语可能是裁剪;切片通常意味着您正在获取一个 N 维数组(例如 3 x 4 x 5)并获取 N- 的数据子集通过为一维选择单个索引来实现一维(即在维度 0 上获取索引 0 以获得 1 x 4 x 5 数组)。
这是一个简短的示例,说明您可以如何执行此操作。让x1 x2 y1 y2
成为您生成的作物的最小和最大 x 和 y 坐标。设ox1 ox2 oy1 oy2
为对象的最小和最大 x 和 y 坐标:
NO_SUCCESSFUL_CROPS = True
while NO_SUCCESSFUL_CROPS:
# Generate crop
x1 = random.randint(0, 1200)
width = random.randint(0, 800)
y1 = random.randint(0, 1200)
height = random.randint(30, 800)
x2 = x1 + width
y2 = y1 + height
# for each bounding box
#check if at least (nominally) 70% of object is within crop
threshold = 0.7
for bbox in all_objects:
#assign bbox to ox1 ox2 oy1 oy2
ox1,ox2,oy1,oy2 = bbox
# compute percentage of bbox that is within crop
minx = max(ox1,x1)
miny = max(oy1,y1)
maxx = min(ox2,x2)
maxy = min(oy2,y2)
area_in_crop = (maxx-minx)*(maxy-miny)
area of bbox = (ox2-ox1)*(oy2-oy1)
ratio = area_in_crop / area_of_bbox
if ratio > threshold:
# break loop
NO_SUCCESSFUL_CROPS = False
# crop image as above
crop_image = image[y1:y2,x1:x2] # if image is an array, may have to do y then x because y is row and x is column. Not sure exactly which form opencv uses
cv2.imwrite("output_file.png",crop_image)
# shift bbox coords since (x1,y1) is the new (0,0) pixel in crop_image
ox1 -= x1
ox2 -= x1
oy1 -= y1
oy2 -= y2
break # no need to continue (although you could alternately continue until you have N crops, or even make sure you get one crop with each object)
推荐阅读
- python - Python遍历字典的json数组
- angular - 打开模态数组Angular的每一项
- kubernetes - 我可以同时使用垂直 pod 自动扩缩器和水平 pod 自动扩缩器吗?
- bash - 如何使 if 语句将 grep 识别为真或假?
- c# - 从 AWS Secret Manager 访问密钥
- javascript - 谷歌脚本以纯文本形式发送电子邮件,而不是 HTML
- asp.net-core - 登录 ASP.NET Core
- android - 如何在非活动课上加分
- jenkins - 简单管道“意外令牌”的 Groovy 编译错误
- java - 每次使用不同参数调用方法时如何创建一个新实例?