backgroundremover
backgroundremover copied to clipboard
Automating background removal for Images using Python libraries, complete guide, api.
NOTE: I didn't want to deal with automating videos as I didn't need them. But you can easily create your own python tool by copying the style of site-packages/backgroundremover/cmd/cli.py for your own usage.
Install those dependincies:
1. A Python version >=3.6 and add it to your path. 2. pytorch(torch, torchvision, torchaudio) from https://pytorch.org/ 3. ffmpeg 4.4+ and add it to your path. 4. backgroundremover package: pip install backgroundremover
Follow these steps:
1. Create a new folder for your project. 2. Inside that project folder, create two more folders named 'images' and 'outputs'. Images folder will contain Images you want to remove backgrounds from. 3. Create a python file and copy+paste my command at the bottom. 4. Run the python file(the first execution of your python file will take couple minutes, it will download necessary modules for background detection. But again, you'll need to install them once.), it will start removing background(the first image will take extra 10~ seconds on every runtime because it'll load modules/model) for every image in 'images' folder and add them _BG_REMOVED suffix then save to 'outputs' folder. 5. If you need to import this to some project else for manual use, "from backgroundapi import remove_image_background, remove_background_from_every_image_in_folder" the first function will take an input path and an output path and run the api for a single image; the second function will take an input folder and an output folder and bulk remove backgrounds for every image that has a image extension and save them to outputs folder, if no output folders provided it'll generate in the provided image folder.
This process took 0.8 seconds for each image for me on a 900M series NVIDIA GPU.
Here's the Python code:
import os
from time import perf_counter
from datetime import timedelta
def remove_image_background(input_path, output_path, debugger=False):
''' NOTE: Models and modules will take some extra time to load during your first execution.\n
NOTE: If you want to play around with the default parameters, check https://github.com/nadermx/backgroundremover see what they mean.\n
Set 'debugger=True' to see execution debugs.\n
'''
# Set default parameters for background remover function.
default_parameters = {
'model': 'u2net',
'alpha_matting': False,
'alpha_matting_foreground_threshold': 240,
'alpha_matting_background_threshold': 10,
'alpha_matting_erode_size': 10,
'alpha_matting_base_size': 1000,
}
# Convert paths to absolute paths.
input_path, output_path = os.path.abspath(input_path), os.path.abspath(output_path)
# Check if paths exist.
if not os.path.exists(input_path):
raise OSError(f'Path {input_path} does not exist.')
if not os.path.exists(os.path.dirname(output_path)):
raise OSError(f'Path {output_path} does not exist.')
# Load modules if running for the first time.
if 'modules_imported' not in globals():
global modules_imported, remove, utilities
if debugger: print("Running app for the first time, importing modules.")
from backgroundremover import utilities
from backgroundremover.bg import remove
modules_imported = ''
# Open input image.
with open(input_path, 'rb') as file:
image = file.read()
# Load model for the first time.
if 'model_loaded' not in globals():
global model_loaded
if debugger: print('Loading model...')
model_loaded = ''
# Remove background from the image and return it as a bytes object.
t1 = perf_counter()
img_removed_bg_bytes = remove(image, model_name=default_parameters['model'],alpha_matting=default_parameters['alpha_matting'], alpha_matting_foreground_threshold=default_parameters['alpha_matting_foreground_threshold'],alpha_matting_background_threshold=default_parameters['alpha_matting_background_threshold'],alpha_matting_erode_structure_size=default_parameters['alpha_matting_erode_size'],alpha_matting_base_size=default_parameters['alpha_matting_base_size'])
if debugger: print(f"{output_path} done. Took {(perf_counter()-t1):003} seconds.")
# Write bytes object to your output path.
with open(output_path, 'wb') as file:
file.write(img_removed_bg_bytes)
def remove_background_from_every_image_in_folder(images_folder = 'images', output_folder = None, output_suffix = '_BG_REMOVED', debugger:bool=True):
'''BE CAREFUL! If images in your images_folder contains the set output_suffix, they won't have their backgrounds removed.
'''
# Failed images
failed = []
# Get absolute path
images_folder = os.path.abspath(images_folder)
if not os.path.exists(images_folder): os.makedirs(images_folder)
if not output_folder: output_folder = images_folder
else:
if not os.path.exists(os.path.abspath(output_folder)): os.makedirs(os.path.abspath(output_folder))
# Declare accepted image extensions and add a dot in front of every element.
image_formats = list(map(lambda x: '.'+x, ["JPEG", "JPG", "PNG", "GIF", "BMP", "TIFF", "TIF","WEBP", "ICO", "EPS", "SVG", "PDF", "RAW", "PCX","XBM", "XPM", "JP2", "EXR", "HDR", "TGA", "PGM","PPM", "PBM", "PAM", "SR", "RAS", "JPE", "JFIF","JIF", "JPE", "JFI", "HEIF", "AVIF", "BPG", "BPGU","FLIF", "JPEG2000", "DJVU", "PGF", "WMF", "EMF","ICNS", "ANI", "MNG", "APNG", "ICO", "CUR","DDS", "PVR", "KTX", "ASTC", "S3TC", "BMP", "ICO","CUR", "WBMP", "XWD", "ART", "PCT", "PLT", "PBM","XPM", "RGB", "RGBA", "BGR", "BGRA", "CMYK", "YCbCr","YUV", "HSV", "LAB", "XYZ", "YCC", "CIE", "LCH","GRAY", "HSL", "HSB", "IPTC", "ICC", "EXIF",]))
# Extend the list for both upper and lower cases.
image_formats = list(map(lambda x: x.lower(), image_formats)) + image_formats
# Get images' paths if their extensions end with an image extension.
images_paths = [os.path.abspath(os.path.join(images_folder, image)) for image in os.listdir(images_folder) if os.path.splitext(image)[-1] in image_formats and output_suffix not in os.path.splitext(image)[0]]
# Run script for every image in the set folder.
for counter, image_path in enumerate(images_paths):
# Get the file name of an image_path, Split by image name and extension.
image_name, extension = os.path.splitext(os.path.basename(image_path))
# Add suffix to base image name
output_image_name = image_name + output_suffix + '.png'
# Get directory of the image path, get absolute path of that directory, then join output_image_name to that.
output_path = os.path.join(os.path.abspath(output_folder), output_image_name)
# Start a timer for estimation.
t1 = perf_counter()
# Run removing function and handle exceptions.
try:
remove_image_background(image_path, output_path, debugger=debugger)
# Exit if KeyboardInterrupt(ctrl+c).
except Exception as e:
if e != KeyboardInterrupt:
print(f"Image content is corrupted or unreadible by this library for: {image_path}")
failed.append(image_path)
continue
else: exit()
# Print time it took if debugger=True
estimated_time = (perf_counter()-t1) * (len(images_paths) - (counter+1))
if debugger: print(f"{counter+1}/{len(images_paths)} OK | ETA: {timedelta(seconds = estimated_time)}", end='\r')
# Done.
if failed:
print(f"\nALL FILES ARE DONE.\n")
print(f"\nFailed to process following file(s): {failed} ")
input('Enter to exit.')
if __name__ == '__main__':
remove_background_from_every_image_in_folder(images_folder='images', output_folder='outputs', output_suffix='_BG_REMOVED', debugger=True)
Intresting, I feel there is just a simple way to feed this into the cmd.py file so it could be part of the command line
works great. Thanks
Damnit, now I might have to find motivation to implement this. Thanks
On Wed, Mar 27, 2024, 2:39 PM stevens-Ai @.***> wrote:
works great. Thanks
— Reply to this email directly, view it on GitHub https://github.com/nadermx/backgroundremover/issues/99#issuecomment-2023944682, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABYACXFAQPXMOLFNOJAPJ5TY2MOAFAVCNFSM6AAAAAA5CMQI5WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMRTHE2DINRYGI . You are receiving this because you commented.Message ID: @.***>