Обрезать несколько ограничивающих рамок из изображения со списком ограничивающих рамок - PullRequest
2 голосов
/ 13 января 2020

Используя Amazon Rekognition, я извлек интересующие ограничивающие рамки из ответа JSON, используя следующее:

    def __init__(self, image):
        self.shape = image.shape 

    def bounding_box_convert(self, bounding_box):

        xmin = int(bounding_box['Left'] * self.shape[1])
        xmax = xmin + int(bounding_box['Width'] * self.shape[1])
        ymin = int(bounding_box['Top'] * self.shape[0])
        ymax = ymin + int(bounding_box['Height'] * self.shape[0])

        return (xmin,ymin,xmax,ymax)

    def polygon_convert(self, polygon):
        pts = []
        for p in polygon:
            x = int(p['X'] * self.shape[1])
            y = int(p['Y'] * self.shape[0])
            pts.append( [x,y] )

        return pts

def get_bounding_boxes(jsondata):
    objectnames = ('Helmet','Hardhat')
    bboxes = []
    a = jsondata
    if('Labels' in a):
        for label in a['Labels']:

            #-- skip over anything that isn't hardhat,helmet
            if(label['Name'] in objectnames):
                print('extracting {}'.format(label['Name']))


                lbl = "{}: {:0.1f}%".format(label['Name'], label['Confidence'])
                print(lbl)

                for instance in label['Instances']:
                    coords = tmp.bounding_box_convert(instance['BoundingBox'])
                    bboxes.append(coords)

    return bboxes

if __name__=='__main__':

    imagefile = 'image011.jpg'
    bgr_image = cv2.imread(imagefile)
    tmp = Tmp(bgr_image)

    jsonname = 'json_000'
    fin = open(jsonname, 'r')

    jsondata = json.load(fin)
    bb = get_bounding_boxes(jsondata)
    print(bb)

Вывод представляет собой список ограничивающих прямоугольников:

[(865, 731, 1077, 906), (1874, 646, 2117, 824)]

Я могу легко извлечь одну позицию из списка и сохранить как новое изображение, используя:

from PIL import Image
img = Image.open("image011.jpg")
area = (865, 731, 1077, 906)
cropped_img = img.crop(area)
cropped_img.save("cropped.jpg")

Однако я не нашел хорошего решения для обрезки и сохранения нескольких ограничивающих рамок из изображения используя вывод списка «bb».

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

Но я считаю, что есть более эффективный способ, чем сохранение данных ограничивающего прямоугольника в CSV и чтение их обратно.

Я не очень силен в написании своих собственных функций - все предложения очень ценятся!

1 Ответ

1 голос
/ 14 января 2020

Предполагая, что ваши ограничивающие координаты имеют форму x,y,w,h, вы можете ROI = image[y:y+h,x:x+w] обрезать. С этим входным изображением:

enter image description here

Используя скрипт из , как получить координаты ограничительной рамки ROI без Guess & Check , чтобы получить x,y,w,h координаты ограничивающего прямоугольника, чтобы обрезать эти области интереса:

enter image description here

Мы просто перебираем список ограничивающего прямоугольника и обрезаем его, используя нарезку Numpy. Извлеченные ROI:

enter image description here

Вот минимальный пример:

import cv2
import numpy as np 

image = cv2.imread('1.png')
bounding_boxes = [(17, 24, 47, 47),
                  (74, 28, 47, 50),
                  (125, 15, 51, 61),
                  (184, 18, 53, 53),
                  (247, 25, 44, 46),
                  (296, 6, 65, 66)
]

num = 0
for box in bounding_boxes:
    x,y,w,h = box
    ROI = image[y:y+h, x:x+w]
    cv2.imwrite('ROI_{}.png'.format(num), ROI)
    num += 1
    cv2.imshow('ROI', ROI)
    cv2.waitKey()
...