如何从图像中检测和删除模糊背景

时间:2017-07-12 09:17:50

标签: opencv image-processing blur background-subtraction

我的图像背景模糊了。我需要做的是删除模糊的背景,只保留锐利的前景物体。他们用openCV做任何方式吗? 图像将类似于下面的图像。我需要检测并减去模糊的背景。

enter image description here

3 个答案:

答案 0 :(得分:3)

这是一项艰巨的任务,因为平坦区域(例如衬衫)具有与模糊区域相同的外观(即低梯度活动)。可以尝试一些分割方法并对每个区域的边缘强度进行评级,但这并不简单。

对于一个穷人的解决方案,这是我尝试过的:

  • 使用边缘检测器并进行二值化,以便包含感兴趣的区域;

  • 执行连通分量分析并选择最大的斑点(模糊区域);

  • 填充blob以获得实体蒙版。

enter image description here

答案 1 :(得分:1)

由于你在评论中提到你不知道从哪里开始,你可以从一个简单的canny边缘检测器开始,它已经为你提供了如何解决问题的提示

Canny at threshold 100, 200

从那时起,您应该寻找合适的迭代来将边缘内的像素映射到新图像。

答案 2 :(得分:1)

这个问题已经开放了一段时间,我从另一个问题被引导到这里。我想我会用一些代码来回答,只是为了将一些实现放在前面答案的想法背后。

从 Canny 边缘检测开始寻找前景:

enter image description here

扩大图像以连接精明的线条。使用 findContours 并选择最大的一个以创建蒙版。

enter image description here

蒙版上有洞,因为轮廓撞到了图像的边缘。我们可以通过反转掩码并再次使用 findContours 来填充小孔。这次我们将过滤掉非常大的轮廓,并将剩余的轮廓绘制到蒙版上。

enter image description here

现在我们只需要使用遮罩来裁剪我们的图像。

enter image description here

这是代码

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);