牢固裁剪照片上的旋转边框 [英] Robustly crop rotated bounding box on photos

查看:94
本文介绍了牢固裁剪照片上的旋转边框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试稳固地提取旋转的轮廓边界框.我想拍摄图像,找到最大的轮廓,获取其旋转的边界框,旋转图像以使边界框垂直,然后裁剪为大小.

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.

为演示起见,这是在以下代码中链接的原始图像.最后,我想把那只鞋旋转到垂直并裁剪成一定的尺寸.以下来自此答案的代码似乎适用于简单图像,例如opencv线等,但不适用于照片.

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.

最后,它被旋转并裁剪错误:

Ends up with this, which is rotated and cropped wrong:

编辑:将阈值类型更改为cv2.THRESH_BINARY_INV后,现在可以正确旋转但裁剪错误:

After changing the threshold type to cv2.THRESH_BINARY_INV, it now is rotated correctly but cropped wrong:

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:

这是我得到的方式:

  • 将原始图像填充到每侧(在我的情况下为500像素)
  • 找到鞋子的四个角点(四个点应形成包围鞋子的多边形,但不必是确切的矩形)
  • 此处使用代码来裁剪鞋子:
  • pad the original image on each side (500 pixels in my case)
  • 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.

这篇关于牢固裁剪照片上的旋转边框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆