首页 > 解决方案 > 有没有办法使用 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 很遗憾,我无法与您分享我的图片。

标签: pythonnumpyopencvyolodarknet

解决方案


模板匹配对此太过分了。模板匹配本质上是在您的主图像上滑动一个内核图像并比较每个像素,执行许多计算。无需搜索图像,因为您已经知道对象在图像中的位置。本质上,您正在尝试确定一个矩形(对象的边界框)是否与切片充分重叠,并且您知道每个矩形的确切坐标。因此,这是一个几何问题而不是计算机视觉问题。

(顺便说一句:您所说的切片的正确术语可能是裁剪;切片通常意味着您正在获取一个 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)

推荐阅读