您的问题不清楚您是要实际裁剪轮廓内定义的信息还是屏蔽与所选轮廓无关的信息。我将探讨在这两种情况下该怎么做。
掩盖信息
假设您在图像上运行cv2.findContours,您将收到一个列出图像中所有可用轮廓的结构。我还假设您知道用于围绕您想要的对象的轮廓的 index。假设它存储在idx 中,首先使用cv2.drawContours 将此轮廓的填充 版本绘制到空白图像上,然后使用此图像索引到您的图像中以提取对象。这种逻辑掩盖任何不相关的信息,只保留重要的信息 - 在您选择的轮廓内定义。执行此操作的代码如下所示,假设您的图像是存储在img 中的灰度图像:
import numpy as np
import cv2
img = cv2.imread('...', 0) # Read in your image
# contours, _ = cv2.findContours(...) # Your call to find the contours using OpenCV 2.4.x
_, contours, _ = cv2.findContours(...) # Your call to find the contours
idx = ... # The index of the contour that surrounds your object
mask = np.zeros_like(img) # Create mask where white is what we want, black otherwise
cv2.drawContours(mask, contours, idx, 255, -1) # Draw filled contour in mask
out = np.zeros_like(img) # Extract out the object and place into output image
out[mask == 255] = img[mask == 255]
# Show the output image
cv2.imshow('Output', out)
cv2.waitKey(0)
cv2.destroyAllWindows()
如果你真的想裁剪...
如果要裁剪图像,则需要定义轮廓定义的区域的最小跨越边界框。您可以找到边界框的左上角和右下角,然后使用索引来裁剪出您需要的内容。代码会和之前一样,但是会有一个额外的裁剪步骤:
import numpy as np
import cv2
img = cv2.imread('...', 0) # Read in your image
# contours, _ = cv2.findContours(...) # Your call to find the contours using OpenCV 2.4.x
_, contours, _ = cv2.findContours(...) # Your call to find the contours
idx = ... # The index of the contour that surrounds your object
mask = np.zeros_like(img) # Create mask where white is what we want, black otherwise
cv2.drawContours(mask, contours, idx, 255, -1) # Draw filled contour in mask
out = np.zeros_like(img) # Extract out the object and place into output image
out[mask == 255] = img[mask == 255]
# Now crop
(y, x) = np.where(mask == 255)
(topy, topx) = (np.min(y), np.min(x))
(bottomy, bottomx) = (np.max(y), np.max(x))
out = out[topy:bottomy+1, topx:bottomx+1]
# Show the output image
cv2.imshow('Output', out)
cv2.waitKey(0)
cv2.destroyAllWindows()
裁剪代码的工作原理是,当我们定义掩码以提取轮廓定义的区域时,我们还会找到定义轮廓左上角的最小水平和垂直坐标。我们同样找到定义轮廓左下角的最大水平和垂直坐标。然后,我们使用这些坐标的索引来裁剪我们实际需要的内容。请注意,这会在 蒙版 图像上执行裁剪 - 该图像会删除除最大轮廓中包含的信息之外的所有内容。
OpenCV 3.x 的注意事项
需要注意的是,上面的代码假设您使用的是 OpenCV 2.4.x。请注意,在 OpenCV 3.x 中,cv2.findContours 的定义发生了变化。具体来说,输出是一个三元素元组输出,其中第一个图像是源图像,而其他两个参数与 OpenCV 2.4.x 中的相同。因此,只需将上述代码中的cv2.findContours 语句更改为忽略第一个输出即可:
_, contours, _ = cv2.findContours(...) # Your call to find contours