如何从图像中删除背景

Mar*_* B. 8 python opencv computer-vision

在此输入图像描述示例图片 我想删除背景,并绘制图像中显示的框的轮廓(有多个具有相似背景的此类图像)。我在 OpenCV 中尝试了多种方法,但是我无法确定可以帮助删除该图像背景的功能组合。尝试过的一些方法是:

  • 边缘检测 - 由于背景本身有自己的边缘,因此单独使用边缘检测(例如 Canny 和 Sobel)似乎没有给出好的结果。
  • 通道过滤/阈值-背景和前景都有相似的白色,所以我无法找到正确的阈值来过滤前景。
  • 轮廓检测 - 由于背景本身有很多轮廓,仅使用最大的轮廓区域(通常用于背景去除)也是行不通的。

我愿意使用计算机视觉或深度学习(Python)中的工具来解决这个特定问题。

Ann*_*Zen 22

这个概念

在这种情况下,微调用于膨胀和腐蚀从图像中检测到的精明边缘的内核非常有用。这是一个示例,其中膨胀内核为np.ones((4, 2)),腐蚀内核为np.ones((13, 7))

代码

import cv2
import numpy as np

def process(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_blur = cv2.GaussianBlur(img_gray, (3, 3), 2)
    img_canny = cv2.Canny(img_blur, 50, 9)
    img_dilate = cv2.dilate(img_canny, np.ones((4, 2)), iterations=11)
    img_erode = cv2.erode(img_dilate, np.ones((13, 7)), iterations=4)
    return cv2.bitwise_not(img_erode)

def get_contours(img):
    contours, _ = cv2.findContours(process(img), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    cnt = max(contours, key=cv2.contourArea)
    cv2.drawContours(img, [cv2.convexHull(cnt)], -1, (0, 0, 255), 2)

img = cv2.imread("image2.png")
get_contours(img)
cv2.imshow("result", img)

cv2.waitKey(0)
cv2.destroyAllWindows()
Run Code Online (Sandbox Code Playgroud)

输出

提供的两个图像的输出:

图片1:

在此输入图像描述

图片2:

在此输入图像描述

笔记

请注意,处理后的图像(二进制)在 处反转cv2.bitwise_not(img_erode)。观察两个图像的处理版本(由process()上面定义的函数返回),并进行反转:

处理后的图像 1:

在此输入图像描述

处理后的图像 2:

在此输入图像描述

工具

最后,如果您碰巧有其他图像,上述程序无法正常工作,您可以使用OpenCV Trackbars通过以下程序调整传递到方法中的值:

import cv2
import numpy as np

def process(img, b_k, b_s, c_t1, c_t2, k1, k2, k3, k4, iter1, iter2):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    b_k = b_k // 2 * 2 + 1
    img_blur = cv2.GaussianBlur(img_gray, (b_k, b_k), b_s)
    img_canny = cv2.Canny(img_blur, c_t1, c_t2)
    img_dilate = cv2.dilate(img_canny, np.ones((k1, k2)), iterations=iter1)
    img_erode = cv2.erode(img_dilate, np.ones((k3, k4)), iterations=iter2)
    return cv2.bitwise_not(img_erode)

d = {"Blur Kernel": (3, 50),
     "Blur Sigma": (2, 30),
     "Canny Threshold 1": (50, 500),
     "Canny Threshold 2": (9, 500),
     "Dilate Kernel1": (4, 50),
     "Dilate Kernel2": (2, 50),
     "Erode Kernel1": (13, 50),
     "Erode Kernel2": (7, 50),
     "Dilate Iterations": (11, 40),
     "Erode Iterations": (4, 40)}

cv2.namedWindow("Track Bars")
for i in d:
    cv2.createTrackbar(i, "Track Bars", *d[i], id)

img = cv2.imread("image1.png")

while True:
    img_copy = img.copy()
    processed = process(img, *(cv2.getTrackbarPos(i, "Track Bars") for i in d))
    contours, _ = cv2.findContours(processed, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    if contours:
        cnt = max(contours, key=cv2.contourArea)
        cv2.drawContours(img_copy, [cv2.convexHull(cnt)], -1, (0, 0, 255), 2)
    cv2.imshow("result", img_copy)
    
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

cv2.waitKey(0)
cv2.destroyAllWindows()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Par*_* MA 7

您可以使用Rembg(删除图像背景的工具)。即使使用预先训练的重量,这也能很好地发挥作用。我尝试了测试图像,这是我使用 Rembg 的结果 在此输入图像描述在此输入图像描述

您可以使用 pip 简单地下载 Rembg

pip install rembg
Run Code Online (Sandbox Code Playgroud)

从单个文件中删除背景

rembg i path/to/input.png path/to/output.png
Run Code Online (Sandbox Code Playgroud)

删除文件夹中所有图像的背景

rembg p path/to/input path/to/output
Run Code Online (Sandbox Code Playgroud)