1+ #! /usr/bin/env bash
2+ # License: GPLv3
3+ # Initial Credits: nadermx
4+ # Credits: Felipe Facundes
5+
6+ set -e
7+
8+ py_venv=" ${HOME} /.python/backgroundremover"
9+ activate=" ${py_venv} /bin/activate"
10+ SUPPORTED_EXTENSIONS=(" png" " jpg" " jpeg" " webp" )
11+
12+ show_help () {
13+ echo " Usage: $( basename " $0 " ) [OPTIONS]"
14+ echo " "
15+ echo " Wrapper around backgroundremover with virtual environment management."
16+ echo " "
17+ echo " Custom options:"
18+ echo " --clean Remove the virtual environment and exit"
19+ echo " --loop <directory> Remove background from all supported images in a directory"
20+ echo " -m <model> Optional model to use (default: u2net)"
21+ echo " Available: u2net, u2net_human_seg, u2netp"
22+ echo " -o <directory> Optional output directory (created if it doesn't exist)"
23+ echo " Default: same directory as input images"
24+ echo " Supported formats: ${SUPPORTED_EXTENSIONS[*]} "
25+ echo " Output files are saved as <name>-rb.png"
26+ echo " "
27+ echo " Examples:"
28+ echo " $( basename " $0 " ) --loop /path/to/images"
29+ echo " $( basename " $0 " ) --loop /path/to/images -m u2net_human_seg"
30+ echo " $( basename " $0 " ) --loop /path/to/images -o /path/to/output"
31+ echo " $( basename " $0 " ) --loop /path/to/images -m u2net_human_seg -o /path/to/output"
32+ echo " $( basename " $0 " ) --clean"
33+ echo " $( basename " $0 " ) -i input.png -o output.png"
34+ echo " "
35+ echo " ----------------------------------------------------------------"
36+ echo " Native backgroundremover help:"
37+ echo " ----------------------------------------------------------------"
38+ echo " "
39+ backgroundremover --help
40+ }
41+
42+ # Remove virtual environment and exit
43+ if [[ " $1 " == " --clean" ]]; then
44+ if [[ -d " ${py_venv} " ]]; then
45+ echo " Cleaning virtual environment..."
46+ rm -rf " ${py_venv} "
47+ echo " Virtual environment removed."
48+ fi
49+ exit 0
50+ fi
51+
52+ # Create virtual environment if it doesn't exist
53+ if [[ ! -d " ${py_venv} " ]]; then
54+ echo " Creating virtual environment at ${py_venv} ..."
55+ python -m venv " ${py_venv} "
56+ # shellcheck source=/dev/null
57+ source " ${activate} "
58+ export VIRTUAL_ENV=" ${py_venv} "
59+ echo " Virtual environment activated: ${VIRTUAL_ENV} "
60+
61+ echo " Upgrading pip..."
62+ pip install --upgrade pip
63+
64+ echo " Installing PyTorch 2.9.0 with CUDA 12.6..."
65+ pip install torch==2.9.0 torchvision==0.24.0 torchaudio==2.9.0 \
66+ --index-url https://download.pytorch.org/whl/cu126
67+
68+ echo " Verifying PyTorch installation..."
69+ python -c "
70+ import torch
71+ print(f'PyTorch version: {torch.__version__}')
72+ print(f'CUDA available: {torch.cuda.is_available()}')
73+ print(f'CUDA version: {torch.version.cuda if torch.cuda.is_available() else \" N/A\" }')
74+ "
75+
76+ echo " Installing backgroundremover..."
77+ pip install backgroundremover
78+ echo " Installation complete!"
79+ else
80+ # shellcheck source=/dev/null
81+ source " ${activate} "
82+ export VIRTUAL_ENV=" ${py_venv} "
83+ echo " Virtual environment activated: ${VIRTUAL_ENV} "
84+ fi
85+
86+ # Show help if no arguments or --help
87+ if [[ $# -eq 0 || " $1 " == " --help" || " $1 " == " -h" ]]; then
88+ show_help
89+ deactivate
90+ exit 0
91+ fi
92+
93+ # --loop: process all images in a directory
94+ if [[ " $1 " == " --loop" ]]; then
95+ input_dir=" $2 "
96+ MODEL=" u2net"
97+ output_dir=" "
98+
99+ # Parse optional arguments
100+ shift 2
101+ while [[ $# -gt 0 ]]; do
102+ case " $1 " in
103+ -m)
104+ MODEL=" $2 "
105+ shift 2
106+ ;;
107+ -o)
108+ output_dir=" $2 "
109+ shift 2
110+ ;;
111+ * )
112+ echo " Error: Unknown argument '$1 ' for --loop."
113+ echo " Usage: $( basename " $0 " ) --loop <directory> [-m <model>] [-o <output_directory>]"
114+ deactivate
115+ exit 1
116+ ;;
117+ esac
118+ done
119+
120+ if [[ -z " ${input_dir} " ]]; then
121+ echo " Error: --loop requires a directory path."
122+ echo " Usage: $( basename " $0 " ) --loop <directory> [-m <model>] [-o <output_directory>]"
123+ deactivate
124+ exit 1
125+ fi
126+
127+ if [[ ! -d " ${input_dir} " ]]; then
128+ echo " Error: '${input_dir} ' is not a directory."
129+ deactivate
130+ exit 1
131+ fi
132+
133+ # Resolve output directory
134+ if [[ -n " ${output_dir} " ]]; then
135+ if [[ ! -d " ${output_dir} " ]]; then
136+ echo " Creating output directory: ${output_dir} "
137+ mkdir -p " ${output_dir} "
138+ fi
139+ fi
140+
141+ # Collect supported images
142+ images=()
143+ for ext in " ${SUPPORTED_EXTENSIONS[@]} " ; do
144+ while IFS= read -r -d ' ' file; do
145+ images+=(" $file " )
146+ done < <( find " ${input_dir} " -maxdepth 1 -iname " *.${ext} " -print0)
147+ done
148+
149+ if [[ ${# images[@]} -eq 0 ]]; then
150+ echo " No supported images found in '${input_dir} '."
151+ echo " Supported formats: ${SUPPORTED_EXTENSIONS[*]} "
152+ deactivate
153+ exit 1
154+ fi
155+
156+ echo " Found ${# images[@]} image(s) to process in '${input_dir} '."
157+ echo " Using model: ${MODEL} "
158+ echo " Output directory: ${output_dir:- ${input_dir} (same as input)} "
159+
160+ SUCCESS=0
161+ FAILED=0
162+ for image in " ${images[@]} " ; do
163+ filename=$( basename " ${image} " )
164+ name=" ${filename% .* } "
165+ dest=" ${output_dir:- ${input_dir} } "
166+ output=" ${dest} /${name} -rb.png"
167+
168+ echo " Processing: ${filename} -> ${output} "
169+ set +e
170+ backgroundremover -i " ${image} " -m " ${MODEL} " -o " ${output} "
171+ if [[ $? -eq 0 ]]; then
172+ (( SUCCESS++ ))
173+ else
174+ echo " Failed: ${filename} "
175+ (( FAILED++ ))
176+ fi
177+ set -e
178+ done
179+
180+ echo " "
181+ echo " Done. Success: ${SUCCESS} | Failed: ${FAILED} "
182+ deactivate
183+ exit 0
184+ fi
185+
186+ # Default: pass arguments directly to backgroundremover
187+ set +e
188+ backgroundremover " $@ "
189+ EXIT_CODE=$?
190+ set -e
191+
192+ deactivate
193+ exit $EXIT_CODE
0 commit comments