我正在使用此处概述的OpenCV GrabCut算法(https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_grabcut/py_grabcut.html#grabcut)来提取图像中的前景。
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('messi5.jpg')
mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (50,50,450,290)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask2[:,:,np.newaxis]
现在,我可以保存通过使用cv.imwrite('filename', img)
获得的图像,并且输出图像仅包含前景,而背景被涂黑。
我想获取前景的边框的坐标为(LowerXcoordinate,LowerYcoordinate)和(UpperXcoordinate,UpperYcoordinate)。
我可以想象的一种方法是将图像视为像素的2D矩阵,要获取较高的Y坐标是从第1行开始,然后逐行检查所有像素的颜色值是否为黑色。具有非黑色像素的第一行将是前景开始的位置。同样,从的最后一行开始,一直向上移动,我可以获得较低的Y坐标。只需对列重复此过程即可获得X坐标。
现在,我所知道的唯一天真的方法是通过手动编写循环来检查这一点。
是否有一些使用库函数来实现此目的的简单方法?
答案 0 :(得分:2)
确实比这容易得多!只需先find the contours of your mask (docs),然后再find the bounding rectangle (docs)。
_, contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
bounding_boxes = [cv2.boundingRect(contour) for contour in contours]
请注意,边界框将由四个项(x, y, w, h)
表示,其中x, y
是左上角,w, h
分别是宽度和高度。遮罩中的每个斑点都会有一个边界框。
此外,重要的提示也很烦人。 OpenCV的旧版本(我认为3.0之前的版本)从findContours()
返回了两个值;只是轮廓和层次。然后在OpenCV 3中进行了更改,并返回了三个值:输入图像,轮廓和层次结构。在OpenCV 4中,将其更改为两个。因此,如果您不使用OpenCV 3,请删除第一个_
。