minareect OpenCV返回的裁剪矩形[Python]

2024-04-18 22:55:42 发布

您现在位置:Python中文网/ 问答频道 /正文

OpenCV中的minAreaRect返回一个旋转的矩形。如何裁剪矩形内的这部分图像?

boxPoints返回旋转矩形的角点坐标,这样人们就可以通过循环遍历框内的点来访问像素,但是在Python中有没有更快的裁剪方法?

编辑

请参阅下面我的答案中的code


Tags: 方法答案图像编辑请参阅code像素opencv
3条回答

这是执行上述任务的代码。为了加快处理速度,不是先旋转整个图像然后裁剪,而是先裁剪部分具有旋转矩形的图像,然后旋转,然后再裁剪以获得最终结果。

# Let cnt be the contour and img be the input

rect = cv2.minAreaRect(cnt)  
box = cv2.boxPoints(rect) 
box = np.int0(box)

W = rect[1][0]
H = rect[1][1]

Xs = [i[0] for i in box]
Ys = [i[1] for i in box]
x1 = min(Xs)
x2 = max(Xs)
y1 = min(Ys)
y2 = max(Ys)

angle = rect[2]
if angle < -45:
    angle += 90

# Center of rectangle in source image
center = ((x1+x2)/2,(y1+y2)/2)
# Size of the upright rectangle bounding the rotated rectangle
size = (x2-x1, y2-y1)
M = cv2.getRotationMatrix2D((size[0]/2, size[1]/2), angle, 1.0)
# Cropped upright rectangle
cropped = cv2.getRectSubPix(img, size, center)
cropped = cv2.warpAffine(cropped, M, size)
croppedW = H if H > W else W
croppedH = H if H < W else W
# Final cropped & rotated rectangle
croppedRotated = cv2.getRectSubPix(cropped, (int(croppedW),int(croppedH)), (size[0]/2, size[1]/2))

下面是执行此任务的函数:

import cv2
import numpy as np

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(rect0)
    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

下面是一个使用示例

# generate image
img = np.zeros((1000, 1000), dtype=np.uint8)
img = cv2.line(img,(400,400),(511,511),1,120)
img = cv2.line(img,(300,300),(700,500),1,120)

# find contours / rectangle
_,contours,_ = cv2.findContours(img, 1, 1)
rect = cv2.minAreaRect(contours[0])

# crop
img_croped = crop_minAreaRect(img, rect)

# show
import matplotlib.pylab as plt
plt.figure()
plt.subplot(1,2,1)
plt.imshow(img)
plt.subplot(1,2,2)
plt.imshow(img_croped)
plt.show()

这是输出

original and croped image

你没有给出样本代码,所以我也没有代码回答。 您可以按以下步骤进行:

  1. 从矩形的角,确定相对于水平轴的旋转角度α。
  2. 按alpha旋转图像,使剪切的矩形与图像边框平行。确保临时图像的大小更大,以便不会丢失任何信息(cf:Rotate image without cropping OpenCV
  3. 使用numpy切片裁剪图像(cf:How to crop an image in OpenCV using Python
  4. 按-alpha旋转图像。

相关问题 更多 >