优化裁剪功能
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)]
。
上面的代码有效但是如何优化代码的速度?它太慢了。还有其他更好的裁剪非矩形补丁的方法吗?
我看到有两个部分可以优化。
- 第一步可以将图像裁剪到边界矩形边界。益处?你大大减少了你正在处理的图像的大小。您只需将 roi 的点平移到矩形的 x,y 就可以了。
- 在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)
来自提供点的蒙版:
背景变黑的图片:
裁剪结果:
我正在使用以下代码裁剪图像并检索非矩形补丁。
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)]
。
上面的代码有效但是如何优化代码的速度?它太慢了。还有其他更好的裁剪非矩形补丁的方法吗?
我看到有两个部分可以优化。
- 第一步可以将图像裁剪到边界矩形边界。益处?你大大减少了你正在处理的图像的大小。您只需将 roi 的点平移到矩形的 x,y 就可以了。
- 在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)
来自提供点的蒙版:
背景变黑的图片:
裁剪结果: