简体   繁体   English

在照片上强健裁剪旋转的边界框

[英]Robustly crop rotated bounding box on photos

I'm trying to extract the rotated bounding box of contours robustly. 我正在努力提取旋转的轮廓边界框。 I would like to take an image, find the largest contour, get its rotated bounding box, rotate the image to make the bounding box vertical, and crop to size. 我想拍摄一张图片,找到最大的轮廓,得到它旋转的边界框,旋转图像使边界框垂直,然后裁剪到大小。

For a demonstration, here is an original image linked in the following code. 对于演示,这是在以下代码中链接的原始图像。 I would like to end up with that shoe rotated to vertical and cropped to size. 我想最终将鞋子旋转到垂直并裁剪成尺寸。 The following code from this answer seems to work on simple images like opencv lines, etc., but not on photos. 此答案中的以下代码似乎适用于简单图像,如opencv线等,但不适用于照片。

在此输入图像描述

Ends up with this, which is rotated and cropped wrong: 结束这个,旋转和裁剪错误:

在此输入图像描述

EDIT: After changing the threshold type to cv2.THRESH_BINARY_INV , it now is rotated correctly but cropped wrong: 编辑:将阈值类型更改为cv2.THRESH_BINARY_INV ,它现在正确旋转但裁剪错误:

在此输入图像描述

import cv2
import matplotlib.pyplot as plt
import numpy as np
import urllib.request
plot = lambda x: plt.imshow(x, cmap='gray').figure


url = 'https://i.imgur.com/4E8ILuI.jpg'
img_path = 'shoe.jpg'

urllib.request.urlretrieve(url, img_path)
img = cv2.imread(img_path, 0)
plot(img)


threshold_value, thresholded_img = cv2.threshold(
    img, 250, 255, cv2.THRESH_BINARY)
_, contours, _ = cv2.findContours(thresholded_img, 1, 1)
contours.sort(key=cv2.contourArea, reverse=True)

shoe_contour = contours[0][:, 0, :]
min_area_rect = cv2.minAreaRect(shoe_contour)

def crop_minAreaRect(img, rect):

    # rotate img
    angle = rect[2]
    rows, cols = img.shape[0], img.shape[1]
    M = cv2.getRotationMatrix2D((cols / 2, rows / 2), angle, 1)
    img_rot = cv2.warpAffine(img, M, (cols, rows))

    # rotate bounding box
    rect0 = (rect[0], rect[1], 0.0)
    box = cv2.boxPoints(rect)
    pts = np.int0(cv2.transform(np.array([box]), M))[0]
    pts[pts < 0] = 0

    # crop
    img_crop = img_rot[pts[1][1]:pts[0][1],
                       pts[1][0]:pts[2][0]]

    return img_crop


cropped = crop_minAreaRect(thresholded_img, min_area_rect)
plot(cropped)

How can I get the correct cropping? 我怎样才能得到正确的裁剪?


After some research, this is what I get: 经过一番研究,这就是我得到的:

在此输入图像描述

This is how I get it: 这就是我得到它的方式:

  • pad the original image on each side (500 pixels in my case) 在每一面填充原始图像(在我的情况下为500像素)
  • find the four corner points of the shoe (the four points should form a polygon enclosing the shoe, but do not need to be exact rectangle) 找到鞋子的四个角点(四个点应该形成一个包围鞋子的多边形,但不一定是精确的矩形)
  • employing the code here to crop the shoe: 使用这里的代码来裁剪鞋子:

img = cv2.imread("padded_shoe.jpg")
# four corner points for padded shoe
cnt = np.array([
    [[313, 794]],
    [[727, 384]],
    [[1604, 1022]],
    [[1304, 1444]]
])
print("shape of cnt: {}".format(cnt.shape))
rect = cv2.minAreaRect(cnt)
print("rect: {}".format(rect))

box = cv2.boxPoints(rect)
box = np.int0(box)
width = int(rect[1][0])
height = int(rect[1][1])

src_pts = box.astype("float32")
dst_pts = np.array([[0, height-1],
                    [0, 0],
                    [width-1, 0],
                    [width-1, height-1]], dtype="float32")
M = cv2.getPerspectiveTransform(src_pts, dst_pts)
warped = cv2.warpPerspective(img, M, (width, height))

Cheers, hope it helps. 干杯,希望它有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM