I'm using the following code to crop an image and retrieve a non-rectangular patch.
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
The roi is [(1053, 969), (1149, 1071), (883, 1075), (813, 983)]
.
The above code works however How do I optimize the speed of the code? It is too slow. Is there any other better way of cropping non-rectangular patches?
I see two parts that could be optimized.
Edit: Modify code to support any number of channels in the input image
The code below does these two things:
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