使用 OpenCV 有条件地去除背景时避免将图像变黑

问题描述 投票:0回答:1

问题描述:

我正在编写一个 Python 脚本,使用 OpenCV 从图像中删除背景。目标是:

检查是否需要去除背景(对于背景简单或均匀的图像,应跳过去除过程)。 仅在必要时应用背景去除,并以透明度保存生成的图像。 目前,当我对不需要的图像(例如,具有简单背景)应用背景去除时,图像最终会变成黑色,而不是保留其原始外观。

我尝试过的:

我通过计算像素强度的方差来检查是否需要去除背景。如果方差很低,我假设背景是均匀的,并且不需要去除背景。 对于具有复杂背景的图像,我使用 OpenCV 应用阈值蒙版来创建透明度。 这是我当前的代码:

import cv2
import numpy as np

# Function to check if background removal is needed
def is_background_removal_needed(image_path):
    image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
    if image is None:
        raise FileNotFoundError(f"Image not found: {image_path}")

    variance = np.var(image)
    print(f"Image variance: {variance:.2f}")
    return variance > 100  # Threshold for variance

# Function to remove background and save transparent image
def remove_background(image_path, output_path):
    image = cv2.imread(image_path)
    if image is None:
        raise FileNotFoundError(f"Image not found: {image_path}")

    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    _, mask = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)

    # Add transparency
    result = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)
    result[:, :, 3] = mask  # Alpha channel

    cv2.imwrite(output_path, result)
    print(f"Background removed and saved to: {output_path}")

# Main process function
def process_image(image_path, output_path):
    if is_background_removal_needed(image_path):
        print("Background removal is needed. Processing...")
        remove_background(image_path, output_path)
    else:
        print("Background removal is NOT needed. Saving the original image.")
        image = cv2.imread(image_path)
        cv2.imwrite(output_path, image)
        print(f"Original image saved to: {output_path}")

# Input and output paths
input_image = "example.jpg"  # Path to input image
output_image = "output_image.png"

# Run the process
process_image(input_image, output_image)

问题: 当我在具有简单或统一背景的图像(例如身份证)上运行此脚本时,应用背景去除过程后输出图像有时会变黑。但是,我希望脚本能够:

检测图像不需要去除背景。 如果不需要处理,则保存原始图像而不进行任何修改。 问题:

为什么应用背景去除后图像有时会变黑? 如何正确跳过简单图像的背景去除并保留原始图像而不改变它? 任何有关改进此脚本的见解或建议将不胜感激。谢谢!

python numpy opencv
1个回答
0
投票

当使用 OpenCV 去除图像中的背景时,如果 alpha 通道(透明度)未得到适当管理或显示,结果通常可能会显示为黑色。

我已尽力完善您的代码。虽然我不能保证它绝对完美地满足您的具体要求,但我希望它能有所帮助。但是,如果修正后的 OpenCV 代码不符合您的期望,您可以考虑使用 Python 库 rembg,它通常会提供出色的结果。

为了您的方便,我在下面提供了更正的 OpenCV 代码和使用 rembg 的示例。

更正opencv:

import cv2
import numpy as np

# Function to check if background removal is needed
def is_background_removal_needed(image_path):
    image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
    if image is None:
       raise FileNotFoundError(f"Image not found: {image_path}")

    variance = np.var(image)
    print(f"Image variance: {variance:.2f}")
    return variance > 100  # Threshold for variance

# Function to remove background and save transparent image
def remove_background(image_path, output_path):
    image = cv2.imread(image_path)
    if image is None:
        raise FileNotFoundError(f"Image not found: {image_path}")

    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    _, mask = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)

    # Add transparency
    original = image.copy()
    # Create an alpha channel based on the mask
    b, g, r = cv2.split(original)
    alpha = mask

    # Merge BGR channels with the alpha channel
    output = cv2.merge((b, g, r, alpha))

    cv2.imwrite(output_path, output)
    print(f"Background removed and saved to: {output_path}")

# Main process function
def process_image(image_path, output_path):
     if is_background_removal_needed(image_path):
         print("Background removal is needed. Processing...")
         remove_background(image_path, output_path)
     else:
         print("Background removal is NOT needed. Saving the original image.")
         image = cv2.imread(image_path)
         cv2.imwrite(output_path, image)
         print(f"Original image saved to: {output_path}")

# Input and output paths
input_image = "example_img.jpg"  # Path to input image
output_image = "output_image.png"

# Run the process
process_image(input_image, output_image)

使用 rembg:

from rembg import remove
from PIL import Image
import io

# Load input image
input_path = 'example_img.jpg'
output_path = 'output_image.png'

with open(input_path, 'rb') as inp_file:
     input_image = inp_file.read()

# Remove the background
output_image = remove(input_image)

# Save the output image (transparent background as PNG)
with open(output_path, 'wb') as out_file:
     out_file.write(output_image)

print(f"Background removed. Saved to {output_path}")
© www.soinside.com 2019 - 2024. All rights reserved.