答案 0 :(得分:3)
这是一项艰巨的任务,因为平坦区域(例如衬衫)具有与模糊区域相同的外观(即低梯度活动)。可以尝试一些分割方法并对每个区域的边缘强度进行评级,但这并不简单。
对于一个穷人的解决方案,这是我尝试过的:
使用边缘检测器并进行二值化,以便包含感兴趣的区域;
执行连通分量分析并选择最大的斑点(模糊区域);
填充blob以获得实体蒙版。
答案 1 :(得分:1)
答案 2 :(得分:1)
这个问题已经开放了一段时间,我从另一个问题被引导到这里。我想我会用一些代码来回答,只是为了将一些实现放在前面答案的想法背后。
从 Canny 边缘检测开始寻找前景:
扩大图像以连接精明的线条。使用 findContours 并选择最大的一个以创建蒙版。
蒙版上有洞,因为轮廓撞到了图像的边缘。我们可以通过反转掩码并再次使用 findContours 来填充小孔。这次我们将过滤掉非常大的轮廓,并将剩余的轮廓绘制到蒙版上。
现在我们只需要使用遮罩来裁剪我们的图像。
这是代码
import cv2
import numpy as np
# load image
img = cv2.imread("foreground.jpg");
# grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY);
# canny
canned = cv2.Canny(gray, 100, 200);
# dilate to close holes in lines
kernel = np.ones((5,5),np.uint8)
mask = cv2.dilate(canned, kernel, iterations = 1);
# find contours
# Opencv 3.4, if using a different major version (4.0 or 2.0), remove the first underscore
_, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE);
# find big contours
biggest_cntr = None;
biggest_area = 0;
for contour in contours:
area = cv2.contourArea(contour);
if area > biggest_area:
biggest_area = area;
biggest_cntr = contour;
# draw contours
crop_mask = np.zeros_like(mask);
cv2.drawContours(crop_mask, [biggest_cntr], -1, (255), -1);
# fill in holes
# inverted
inverted = cv2.bitwise_not(crop_mask);
# contours again
_, contours, _ = cv2.findContours(inverted, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE);
# find small contours
small_cntrs = [];
for contour in contours:
area = cv2.contourArea(contour);
if area < 20000:
print(area);
small_cntrs.append(contour);
# draw on mask
cv2.drawContours(crop_mask, small_cntrs, -1, (255), -1);
# opening + median blur to smooth jaggies
crop_mask = cv2.erode(crop_mask, kernel, iterations = 1);
crop_mask = cv2.dilate(crop_mask, kernel, iterations = 1);
crop_mask = cv2.medianBlur(crop_mask, 5);
# crop image
crop = np.zeros_like(img);
crop[crop_mask == 255] = img[crop_mask == 255];
# show
cv2.imshow("original", img);
cv2.imshow("gray", gray);
cv2.imshow("canny", canned);
cv2.imshow("mask", crop_mask);
cv2.imshow("cropped", crop);
cv2.waitKey(0);