【问题标题】:OpenCV remove backgroundOpenCV 去除背景
【发布时间】:2018-07-14 16:04:23
【问题描述】:

我正在尝试删除一些图像的背景,调整一些值并使用诸如morphologyEx 之类的一些方法给了我一个可以接受的结果,但仍然存在一些漏洞,在最后一种情况下,这些漏洞甚至没有填充甚至迭代每个轮廓并用-1 绘制它。我可以看到阈值图像非常好,用线条制作整个形状,但我不知道如何继续......

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

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 原创

1 个阈值

2 孔

3 最终图像

【问题讨论】:

  • 您的代码不是有效的 Python 代码。请发布没有语法错误的代码(即能够运行的代码)。
  • 缺少括号,现已更新。
  • 你应该先查看一些关于屏蔽的 opencv 教程。另外,看看这个:stackoverflow.com/questions/18710428/…
  • 我已经阅读了一些教程,也阅读了 stackoverflow 问题,但我无法使其正常工作。例如,一些教程是关于 C++ 的,我正在使用 python,但我不知道该怎么做在python中,例如Mat(hsvImg.rows, hsvImg.cols, CV_8UC1, 200)和其他东西......
  • @RobertW.Hunter 然后查看this

标签: python opencv


【解决方案1】:

由于我正在解决相同的问题,并在 Python(使用 opencv2)中找到了解决方案,所以我也想在这里分享一下。希望对您有所帮助。

import numpy as np
import cv2

cv2.namedWindow('image', cv2.WINDOW_NORMAL)

#Load the Image
imgo = cv2.imread('koAl2.jpg')
height, width = imgo.shape[:2]

#Create a mask holder
mask = np.zeros(imgo.shape[:2],np.uint8)

#Grab Cut the object
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)

#Hard Coding the Rect The object must lie within this rect.
rect = (10,10,width-30,height-30)
cv2.grabCut(imgo,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img1 = imgo*mask[:,:,np.newaxis]

#Get the background
background = imgo - img1

#Change all pixels in the background that are not black to white
background[np.where((background > [0,0,0]).all(axis = 2))] = [255,255,255]

#Add the background and the image
final = background + img1

#To be done - Smoothening the edges

cv2.imshow('image', final )

k = cv2.waitKey(0)

if k==27:
    cv2.destroyAllWindows()

【讨论】:

    【解决方案2】:

    使用不断增大的内核迭代地执行孔图像的形态闭合。但是,在这样做之前,我建议您调整孔图像的大小(使用最近邻插值),这样您就不必使用巨大的内核。在以下代码 (C++) 中,我将孔图像的大小调整为原始尺寸的 25%。

    为了减少对边框的影响,在应用迭代关闭之前,使用 copyMakeBorder 添加一个恒定的零边框。由于我们在这里使用了 15 次迭代,因此使图像周围的边框大于 15。

    所以步骤是

    • 调整孔图像的大小
    • 添加零边框
    • 使用不断增大的内核迭代地关闭图像
    • 移除边框
    • 现在我们有了一个小面具。将此蒙版调整为原始图像大小

    代码是 C++。我对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);
    

    输出(不是原始比例)看起来不错,只是它将底部的背景区域作为前景。

    【讨论】:

    • 我无法让它在 python 上运行,有两件事我无法转换为 Python: 1:bordered 刚刚成为一种方法?什么时候? bordered(Rect(b, b, small.cols, small.rows))Rect 是什么? 2:resize(holes, small, Size(), .25, .25)我没有Size()对象,我想这是一个元组??,但我不能使用空元组() 3:morphologyEx(bordered, bordered, MORPH_CLOSE, kernel, Point(-1, -1), 1)在python中变成bordered = cv2.morphologyEx(bordered, cv2.MORPH_CLOSE, kernel, (-1, -1), 1)但是错误:new style getargs format but argument is not a tuple
    • Mat mask = bordered(Rect(b, b, small.cols, small.rows)); 将指定的 ROI 提取到掩码中。它是 Mat 类的运算符。如果您专注于我给出的描述,而不是尝试将 C++ 代码一对一映射到 Python,您将能够完成这项工作。我添加了代码,希望它能使描述更清晰。
    【解决方案3】:

    @dhanushka 的方法效果很好。这是我的pythonic版本:

    def get_holes(image, thresh):
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    
        im_bw = cv.threshold(gray, thresh, 255, cv.THRESH_BINARY)[1]
        im_bw_inv = cv.bitwise_not(im_bw)
    
        contour, _ = cv.findContours(im_bw_inv, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE)
        for cnt in contour:
            cv.drawContours(im_bw_inv, [cnt], 0, 255, -1)
    
        nt = cv.bitwise_not(im_bw)
        im_bw_inv = cv.bitwise_or(im_bw_inv, nt)
        return im_bw_inv
    
    
    def remove_background(image, thresh, scale_factor=.25, kernel_range=range(1, 15), border=None):
        border = border or kernel_range[-1]
    
        holes = get_holes(image, thresh)
        small = cv.resize(holes, None, fx=scale_factor, fy=scale_factor)
        bordered = cv.copyMakeBorder(small, border, border, border, border, cv.BORDER_CONSTANT)
    
        for i in kernel_range:
            kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (2*i+1, 2*i+1))
            bordered = cv.morphologyEx(bordered, cv.MORPH_CLOSE, kernel)
    
        unbordered = bordered[border: -border, border: -border]
        mask = cv.resize(unbordered, (image.shape[1], image.shape[0]))
        fg = cv.bitwise_and(image, image, mask=mask)
        return fg
    
    
    img = cv.imread('koAl2.jpg')
    nb_img = remove_background(img, 230)
    

    【讨论】:

    • python 版本?如何导入简历?
    • ",第 11 行,在 get_holes 轮廓中,_ = cv2.findContours(im_bw_inv, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) ValueError: too many values to unpack
    【解决方案4】:

    @grep,根据 Alexander Lutsenko 的一篇文章,对于 python 3.6.3,要使代码正常工作,您需要向 findContours() 添加一个返回值,如下所示:

    contour, _ = cv.findContours(im_bw_inv, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE)

    _, contour, _ = cv.findContours(im_bw_inv, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE)

    【讨论】:

      【解决方案5】:

      在 C++ 中尝试这种形态学运算来消除空洞和膨胀

      Mat erodeElement = getStructuringElement(MORPH_RECT, Size(4, 4));
      morphologyEx(thresh, thresh, MORPH_CLOSE ,erodeElement);
      morphologyEx(thresh, thresh, MORPH_OPEN, erodeElement);
      morphologyEx(thresh, thresh, MORPH_CLOSE, erodeElement);
      morphologyEx(thresh, thresh, MORPH_OPEN, erodeElement);
      morphologyEx(thresh, thresh, MORPH_OPEN, erodeElement);
      

      【讨论】:

        猜你喜欢
        • 2013-02-24
        • 2018-07-15
        • 2020-05-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多