优化裁剪功能

Optimize the cropping function

我正在使用以下代码裁剪图像并检索非矩形补丁。

def crop_image(img,roi):
    height = img.shape[0]
    width = img.shape[1]

    mask = np.zeros((height, width), dtype=np.uint8)
    points = np.array([roi])
    cv2.fillPoly(mask, points, (255))

    res = cv2.bitwise_and(img, img, mask=mask)

    rect = cv2.boundingRect(points)  # returns (x,y,w,h) of the rect
    cropped = res[rect[1]: rect[1] + rect[3], rect[0]: rect[0] + rect[2]]

    return cropped, res

投资回报率是 [(1053, 969), (1149, 1071), (883, 1075), (813, 983)]。 上面的代码有效但是如何优化代码的速度?它太慢了。还有其他更好的裁剪非矩形补丁的方法吗?

我看到有两个部分可以优化。

  1. 第一步可以将图像裁剪到边界矩形边界。益处?你大大减少了你正在处理的图像的大小。您只需将 roi 的点平移到矩形的 x,y 就可以了。
  2. 在bitwise_and操作中,你是"anding"图像本身,并在每个像素处检查掩码是否允许输出它。我想这是花费最多时间的地方。相反,您可以直接 "and" 使用面具并节省您宝贵的时间(没有额外的面具检查步骤)。同样,为了能够做到这一点,一个小的调整,蒙版图像应该与输入图像(包括通道)具有完全相同的形状。

编辑: 修改代码以支持输入图像中的任意数量的通道

下面的代码做了这两件事:

def crop_image(img, roi):
height = img.shape[0]
width = img.shape[1]
channels = img.shape[2] if len(img.shape) > 2 else 1

points = np.array([roi])

rect = cv2.boundingRect(points)

mask_shape = (rect[3], rect[2]) if channels == 1 else (rect[3], rect[2], img.shape[2])

#Notice how the mask image size is now the size of the bounding rect
mask = np.zeros(mask_shape, dtype=np.uint8)

#tranlsate the points so that their origin is the bounding rect top left point
for p in points[0]:
    p[0] -= rect[0]
    p[1] -= rect[1]


mask_filling = tuple(255 for _ in range(channels))
cv2.fillPoly(mask, points, mask_filling)

cropped = img[rect[1]: rect[1] + rect[3], rect[0]: rect[0] + rect[2]]

res = cv2.bitwise_and(cropped, mask)

return cropped, res

这是使用 Python/OpenCV 和 Numpy 的一种方法。

输入:

import cv2
import numpy as np

# read image
img = cv2.imread("efile.jpg")

points = np.array( [[ [693,67], [23,85], [62,924], [698,918] ]] )

# get bounding rectangle of points
x,y,w,h = cv2.boundingRect(points)
print(x,y,w,h)

# draw white filled polygon from points on black background as mask
mask = np.zeros_like(img)
cv2.fillPoly(mask, points, (255,255,255))

# fill background of image with black according to mask
masked = img.copy()
masked[mask==0] = 0

# crop to bounding rectangle
cropped = masked[y:y+h, x:x+w]

# write results
cv2.imwrite("efile_mask.jpg", mask)
cv2.imwrite("efile_masked.jpg", masked)
cv2.imwrite("efile_cropped.jpg", cropped)

# display it
cv2.imshow("efile_mask", mask)
cv2.imshow("efile_masked", masked)
cv2.imshow("efile_cropped", cropped)
cv2.waitKey(0)


来自提供点的蒙版:

背景变黑的图片:

裁剪结果: