OpenCV删除背景 [英] OpenCV remove background

查看:145
本文介绍了OpenCV删除背景的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图删除某些图像的背景,调整一些值,并使用诸如morphologyEx之类的方法给我一个令人满意的结果,但仍然存在一些孔,在最后一种情况下,这些孔即使在迭代时也无法填充每个轮廓并使用-1进行绘制.我可以看到阈值图像确实非常好,可以使线条整体成形,但是我不知道如何继续...

I am trying to remove the background of some images, tweaking some values and using some methods like morphologyEx gives me an aceptable result but some holes still remaining, in this last case, the holes doesn't fill even iterating on every contour and drawing it with -1. I can see that threshold image is really good, making the whole shape with lines, but I don't know how to continue...

更新 我已经更改了代码,以便获得更好的结果,但是仍然有一些漏洞...如果可以填补这些漏洞,该脚本将是完美的.

Update I've changed my code so I get better results but I'm still getting some holes... If I could fill theese holes, the script would be perfect.

def get_contrasted(image, type="dark", level=3):
    maxIntensity = 255.0 # depends on dtype of image data
    phi = 1
    theta = 1

    if type == "light":
        newImage0 = (maxIntensity/phi)*(image/(maxIntensity/theta))**0.5
        newImage0 = array(newImage0,dtype=uint8)
        return newImage0
    elif type == "dark":
        newImage1 = (maxIntensity/phi)*(image/(maxIntensity/theta))**level
        newImage1 = array(newImage1,dtype=uint8)

        return newImage1

def sharp(image, level=3):
    f = cv2.GaussianBlur(image, (level,level), level)
    f = cv2.addWeighted(image, 1.5, f, -0.5, 0)
    return f

original_image = imread('imagen.jpg')
# 1 Convert to gray & Normalize
gray_img = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
gray_img = sharp(get_contrasted(gray_img))
gray_img = normalize(gray_img, None, 0, 255, NORM_MINMAX, CV_8UC1)
imshow("Gray", gray_img)

# 2 Find Threshold
gray_blur = cv2.GaussianBlur(gray_img, (7, 7), 0)
adapt_thresh_im = cv2.adaptiveThreshold(gray_blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 1)
max_thresh, thresh_im = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
thresh = cv2.bitwise_or(adapt_thresh_im, thresh_im)

# 3 Dilate
gray = cv2.Canny(thresh, 88, 400, apertureSize=3)
gray = cv2.dilate(gray, None, iterations=8)
gray = cv2.erode(gray, None, iterations=8)
imshow("Trheshold", gray)

# 4 Flood
contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contour_info = []
for c in contours:
    contour_info.append((
        c,
        cv2.isContourConvex(c),
        cv2.contourArea(c),
    ))
contour_info = sorted(contour_info, key=lambda c: c[2], reverse=True)
max_contour = contour_info[0]
holes = np.zeros(gray_img.shape, np.uint8)
drawContours(holes, max_contour, 0, 255, -1)
imshow("Holes", holes)

mask = cv2.GaussianBlur(holes, (15, 15), 0)
mask = np.dstack([mask] * 3)  # Create 3-channel alpha mask

mask = mask.astype('float32') / 255.0  # Use float matrices,
img = original_image.astype('float32') / 255.0  # for easy blending
masked = (mask * img) + ((1 - mask) * (0,0,1))  # Blend
masked = (masked * 255).astype('uint8')

imshow("Maked", masked)
waitKey()

0原始

推荐答案

使用大小增加的核迭代地对孔图像进行形态学封闭.但是,在执行此操作之前,我建议您调整孔图像的大小(使用最近邻插值法),这样就不必使用巨大的内核.在以下代码(C ++)中,我将孔图像的大小调整为其原始尺寸的25%.

Iteratively perform a morphological closing of your holes image using a kernel of increasing size. But, before doing this I suggest you resize the holes image (using nearest-neighbor interpolation) so you don't have to use huge kernels. In the following code (C++), I resized the holes image to 25% of its original dimensions.

要减少对边界的影响,请在应用迭代结束之前使用 copyMakeBorder 添加恒定的零边界.当我们在这里使用15次迭代时,使图像周围的边界大于15.

To reduce the effects on borders add a constant border of zeros using copyMakeBorder before you apply the iterative closing. As we are using 15 iterations here, make the border around the image larger than 15.

步骤是

  • 调整孔图像的大小
  • 添加零边框
  • 使用大小逐渐增加的内核迭代关闭图像
  • 删除边框
  • 现在我们有一个小口罩.将此蒙版调整为原始图像大小

代码使用C ++.我对python不太熟悉.

The code is in C++. I'm not very familiar with python.

    // read the image and the holes
    Mat im = imread("koAl2.jpg");
    Mat holes = imread("GuICX.jpg", 0);
    // resize
    Mat small, bordered;
    resize(holes, small, Size(), .25, .25);
    // add a zero border
    int b = 20;
    copyMakeBorder(small, bordered, b, b, b, b, BORDER_CONSTANT, Scalar(0));
    // close
    for (int i = 1; i < 15; i++)
    {
        Mat kernel = getStructuringElement(MORPH_ELLIPSE, cv::Size(2*i+1, 2*i+1));
        morphologyEx(bordered, bordered, MORPH_CLOSE, kernel, Point(-1, -1), 1);
    }
    // remove border
    Mat mask = bordered(Rect(b, b, small.cols, small.rows));
    // resize the mask
    Mat largeMask;
    resize(mask, largeMask, Size(im.cols, im.rows));
    // the foreground
    Mat fg;
    im.copyTo(fg, largeMask);

除了将底部的背景区域作为前景之外,输出(不是原始比例)看起来不错.

The output (not to original scale) looks fine except that it takes the background region at the bottom as foreground.

这篇关于OpenCV删除背景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆