Spaces:
Sleeping
Sleeping
Add option to toggle transparency processing
Browse filesIntroduced a `use_transparency` parameter to allow users to choose between RGBA (transparent) and RGB (opaque) processing modes via the UI.
app.py
CHANGED
|
@@ -1489,6 +1489,7 @@ def stitch_pairwise_images(img_composite, img_new,
|
|
| 1489 |
|
| 1490 |
# --- Function for N-Image Stitching (Primarily for Image List Input) ---
|
| 1491 |
def stitch_multiple_images(images, # List of NumPy images (BGR/BGRA, potentially pre-cropped)
|
|
|
|
| 1492 |
stitcher_mode_str="SCANS",
|
| 1493 |
registration_resol=0.6,
|
| 1494 |
seam_estimation_resol=0.1,
|
|
@@ -1509,14 +1510,15 @@ def stitch_multiple_images(images, # List of NumPy images (BGR/BGRA, potentially
|
|
| 1509 |
max_blending_height=10000,
|
| 1510 |
blend_smooth_ksize=15,
|
| 1511 |
num_blend_levels=4,
|
| 1512 |
-
fixed_base_image_index=-1
|
| 1513 |
):
|
| 1514 |
"""
|
| 1515 |
Stitches a list of images. Tries cv2.Stitcher first (unless 'DIRECT_PAIRWISE'),
|
| 1516 |
otherwise falls back to manual pairwise stitching.
|
| 1517 |
Returns ONE stitched image (RGB/RGBA) and log.
|
| 1518 |
-
Input images should be in BGR format (already potentially cropped by caller).
|
| 1519 |
Output is RGBA. The 'enable_cropping' param here refers to final black border cropping.
|
|
|
|
| 1520 |
"""
|
| 1521 |
log = log_and_print(f"--- Starting Stitching Process for {len(images)} Provided Images ---\n", "")
|
| 1522 |
total_start_time = time.time()
|
|
@@ -1796,7 +1798,8 @@ def stitch_multiple_images(images, # List of NumPy images (BGR/BGRA, potentially
|
|
| 1796 |
|
| 1797 |
# Clean up the input image list now that it's processed
|
| 1798 |
del images
|
| 1799 |
-
if 'valid_images' in locals():
|
|
|
|
| 1800 |
gc.collect()
|
| 1801 |
|
| 1802 |
# 3. Final Result Check and Return (Handling Alpha Channel)
|
|
@@ -1806,15 +1809,26 @@ def stitch_multiple_images(images, # List of NumPy images (BGR/BGRA, potentially
|
|
| 1806 |
if stitched_img_bgra is not None and stitched_img_bgra.size > 0:
|
| 1807 |
log = log_and_print("Stitching process finished for image list.", log)
|
| 1808 |
try:
|
| 1809 |
-
#
|
| 1810 |
-
if
|
|
|
|
|
|
|
| 1811 |
# Convert BGRA to RGBA
|
| 1812 |
-
|
| 1813 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1814 |
else:
|
| 1815 |
-
#
|
| 1816 |
-
|
| 1817 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1818 |
|
| 1819 |
del stitched_img_bgra # Release BGRA version
|
| 1820 |
gc.collect()
|
|
@@ -1834,6 +1848,7 @@ def stitch_multiple_images(images, # List of NumPy images (BGR/BGRA, potentially
|
|
| 1834 |
|
| 1835 |
# --- Video Frame Stitching ---
|
| 1836 |
def stitch_video_frames(video_path,
|
|
|
|
| 1837 |
crop_top_percent=0.0,
|
| 1838 |
crop_bottom_percent=0.0,
|
| 1839 |
enable_cropping=True, # This is for POST-stitch cropping
|
|
@@ -1854,10 +1869,11 @@ def stitch_video_frames(video_path,
|
|
| 1854 |
sample_interval_ms=3000,
|
| 1855 |
max_composite_width=10000,
|
| 1856 |
max_composite_height=10000,
|
| 1857 |
-
progress=None
|
|
|
|
| 1858 |
"""
|
| 1859 |
Reads a video, samples frames, and stitches them sequentially.
|
| 1860 |
-
Returns a list of stitched images (RGBA
|
| 1861 |
"""
|
| 1862 |
log = log_and_print(f"--- Starting Incremental Video Stitching: {os.path.basename(video_path)} ---\n", "")
|
| 1863 |
log = log_and_print(f"Params: Interval={sample_interval_ms}ms, Transform={transform_model_str}, ORB={orb_nfeatures}, Ratio={match_ratio_thresh}\n", log)
|
|
@@ -1867,7 +1883,7 @@ def stitch_video_frames(video_path,
|
|
| 1867 |
log = log_and_print(f"Post-Crop Black Borders: {enable_cropping}, Strict Edges: {strict_no_black_edges}\n", log)
|
| 1868 |
log = log_and_print(f"Blending: Method={blend_method}, GainComp={enable_gain_compensation}, SmoothKSize={blend_smooth_ksize}, MB Levels={num_blend_levels}\n", log)
|
| 1869 |
total_start_time = time.time()
|
| 1870 |
-
stitched_results_rgba = [] # Store final RGBA
|
| 1871 |
|
| 1872 |
cap = cv2.VideoCapture(video_path)
|
| 1873 |
if not cap.isOpened():
|
|
@@ -1900,10 +1916,17 @@ def stitch_video_frames(video_path,
|
|
| 1900 |
# Helper to save image to results list with correct color conversion
|
| 1901 |
def append_result(img_bgr_or_bgra):
|
| 1902 |
try:
|
| 1903 |
-
if
|
| 1904 |
-
|
|
|
|
|
|
|
|
|
|
| 1905 |
else:
|
| 1906 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1907 |
return True
|
| 1908 |
except Exception as e:
|
| 1909 |
print(f"Error converting result: {e}")
|
|
@@ -1925,25 +1948,41 @@ def stitch_video_frames(video_path,
|
|
| 1925 |
if frame_bgr_raw is not None and frame_bgr_raw.size > 0:
|
| 1926 |
processed_sampled_count += 1
|
| 1927 |
frame_bgra = None # Initialize BGR frame variable
|
| 1928 |
-
|
| 1929 |
-
#
|
| 1930 |
-
if
|
| 1931 |
-
|
| 1932 |
-
|
| 1933 |
-
#
|
| 1934 |
-
|
| 1935 |
-
|
| 1936 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1937 |
else:
|
| 1938 |
-
|
| 1939 |
-
if frame_bgr_raw
|
| 1940 |
-
|
| 1941 |
-
|
| 1942 |
-
|
| 1943 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1944 |
|
| 1945 |
# Release the raw frame once converted/checked (if a copy was made)
|
| 1946 |
-
if frame_bgra is not frame_bgr_raw:
|
| 1947 |
del frame_bgr_raw
|
| 1948 |
frame_bgr_raw = None # Mark as deleted
|
| 1949 |
gc.collect()
|
|
@@ -2246,6 +2285,7 @@ def stitch_video_frames(video_path,
|
|
| 2246 |
|
| 2247 |
# --- Gradio Interface Function ---
|
| 2248 |
def run_stitching_interface(input_files,
|
|
|
|
| 2249 |
crop_top_percent,
|
| 2250 |
crop_bottom_percent,
|
| 2251 |
stitcher_mode_str, # For cv2.Stitcher
|
|
@@ -2413,6 +2453,7 @@ def run_stitching_interface(input_files,
|
|
| 2413 |
|
| 2414 |
final_stitched_images_rgba, stitch_log = stitch_video_frames(
|
| 2415 |
video_path,
|
|
|
|
| 2416 |
crop_top_percent=crop_top_percent,
|
| 2417 |
crop_bottom_percent=crop_bottom_percent,
|
| 2418 |
enable_cropping=enable_cropping, # Post-stitch crop
|
|
@@ -2445,11 +2486,16 @@ def run_stitching_interface(input_files,
|
|
| 2445 |
try:
|
| 2446 |
n = np.fromfile(img_path, np.uint8)
|
| 2447 |
if n.size > 0:
|
|
|
|
|
|
|
| 2448 |
# Use IMREAD_UNCHANGED to keep Alpha
|
| 2449 |
img = cv2.imdecode(n, cv2.IMREAD_UNCHANGED)
|
|
|
|
|
|
|
| 2450 |
else:
|
| 2451 |
-
|
| 2452 |
-
|
|
|
|
| 2453 |
if img is None:
|
| 2454 |
raise ValueError("imdecode returned None")
|
| 2455 |
except Exception as e_read:
|
|
@@ -2458,22 +2504,36 @@ def run_stitching_interface(input_files,
|
|
| 2458 |
del img
|
| 2459 |
continue # Skip to the next image
|
| 2460 |
|
| 2461 |
-
# Convert to BGRA for consistency
|
|
|
|
| 2462 |
img_bgra = None
|
| 2463 |
try:
|
| 2464 |
-
if
|
| 2465 |
-
|
| 2466 |
-
|
| 2467 |
-
|
| 2468 |
-
|
| 2469 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2470 |
else:
|
| 2471 |
-
|
| 2472 |
-
|
| 2473 |
-
|
| 2474 |
-
|
| 2475 |
-
|
| 2476 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2477 |
except cv2.error as e_cvt_color:
|
| 2478 |
log = log_and_print(f"Error converting image color for {os.path.basename(img_path)}: {e_cvt_color}. Skipping.\n", log)
|
| 2479 |
del img
|
|
@@ -2516,7 +2576,8 @@ def run_stitching_interface(input_files,
|
|
| 2516 |
|
| 2517 |
# Call the modified stitch_multiple_images function
|
| 2518 |
stitched_single_rgba, stitch_log_img = stitch_multiple_images(
|
| 2519 |
-
images_bgr_cropped, # Pass the list of cropped images (BGRA)
|
|
|
|
| 2520 |
stitcher_mode_str=stitcher_mode_str,
|
| 2521 |
registration_resol=registration_resol,
|
| 2522 |
seam_estimation_resol=seam_estimation_resol,
|
|
@@ -2618,12 +2679,19 @@ def run_stitching_interface(input_files,
|
|
| 2618 |
full_path = os.path.join(temp_dir, filename)
|
| 2619 |
img_bgra = None # Initialize for finally block
|
| 2620 |
try:
|
| 2621 |
-
|
| 2622 |
-
|
| 2623 |
-
|
| 2624 |
-
|
|
|
|
|
|
|
|
|
|
| 2625 |
else:
|
| 2626 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2627 |
|
| 2628 |
# Use imencode -> write pattern for better handling of paths/special chars
|
| 2629 |
is_success, buf = cv2.imencode('.png', img_bgra)
|
|
@@ -2685,6 +2753,8 @@ with gr.Blocks() as demo:
|
|
| 2685 |
|
| 2686 |
# --- Parameters Grouping ---
|
| 2687 |
with gr.Accordion("Preprocessing Settings", open=True):
|
|
|
|
|
|
|
| 2688 |
crop_top_percent = gr.Slider(0.0, 49.0, step=0.5, value=0.0, label="Crop Top %",
|
| 2689 |
info="Percentage of height to remove from the TOP of each image/frame BEFORE stitching.")
|
| 2690 |
crop_bottom_percent = gr.Slider(0.0, 49.0, step=0.5, value=0.0, label="Crop Bottom %",
|
|
@@ -2762,6 +2832,7 @@ with gr.Blocks() as demo:
|
|
| 2762 |
inputs=[
|
| 2763 |
input_files,
|
| 2764 |
# Preprocessing
|
|
|
|
| 2765 |
crop_top_percent,
|
| 2766 |
crop_bottom_percent,
|
| 2767 |
# OpenCV Stitcher (Image List)
|
|
@@ -2797,7 +2868,7 @@ with gr.Blocks() as demo:
|
|
| 2797 |
examples = [
|
| 2798 |
[
|
| 2799 |
["examples/Wetter-Panorama/Wetter-Panorama1[NIuO6hrFTrg].mp4"],
|
| 2800 |
-
0, 20,
|
| 2801 |
"DIRECT_PAIRWISE", 0.6, 0.1, -1, False, "GAIN_BLOCKS",
|
| 2802 |
True, False, -1,
|
| 2803 |
"Homography", "Multi-Band", True, 5000, 0.5, 5.0, 0.5, 10000, 10000, 15, 4,
|
|
@@ -2805,7 +2876,7 @@ with gr.Blocks() as demo:
|
|
| 2805 |
],
|
| 2806 |
[
|
| 2807 |
["examples/Wetter-Panorama/Wetter-Panorama2[NIuO6hrFTrg].mp4"],
|
| 2808 |
-
0, 20,
|
| 2809 |
"DIRECT_PAIRWISE", 0.6, 0.1, -1, False, "GAIN_BLOCKS",
|
| 2810 |
True, False, -1,
|
| 2811 |
"Homography", "Multi-Band", True, 5000, 0.5, 5.0, 0.5, 10000, 10000, 15, 4,
|
|
@@ -2814,7 +2885,7 @@ with gr.Blocks() as demo:
|
|
| 2814 |
[
|
| 2815 |
["examples/NieRAutomata/nier2B_01.jpg", "examples/NieRAutomata/nier2B_02.jpg", "examples/NieRAutomata/nier2B_03.jpg", "examples/NieRAutomata/nier2B_04.jpg", "examples/NieRAutomata/nier2B_05.jpg",
|
| 2816 |
"examples/NieRAutomata/nier2B_06.jpg", "examples/NieRAutomata/nier2B_07.jpg", "examples/NieRAutomata/nier2B_08.jpg", "examples/NieRAutomata/nier2B_09.jpg", "examples/NieRAutomata/nier2B_10.jpg", ],
|
| 2817 |
-
0, 0,
|
| 2818 |
"PANORAMA", 0.6, 0.1, -1, False, "GAIN_BLOCKS",
|
| 2819 |
True, False, -1,
|
| 2820 |
"Homography", "Multi-Band", True, 5000, 0.5, 5.0, 0.5, 10000, 10000, 15, 4,
|
|
@@ -2822,7 +2893,7 @@ with gr.Blocks() as demo:
|
|
| 2822 |
],
|
| 2823 |
[
|
| 2824 |
["examples/cat/cat_left.jpg", "examples/cat/cat_right.jpg"],
|
| 2825 |
-
0, 0,
|
| 2826 |
"SCANS", 0.6, 0.1, -1, False, "GAIN_BLOCKS",
|
| 2827 |
True, False, -1,
|
| 2828 |
"Affine_Partial", "Linear", True, 5000, 0.5, 5.0, 0.5, 10000, 10000, 15, 4,
|
|
@@ -2830,7 +2901,7 @@ with gr.Blocks() as demo:
|
|
| 2830 |
],
|
| 2831 |
[
|
| 2832 |
["examples/ギルドの受付嬢ですが/Girumasu_1.jpg", "examples/ギルドの受付嬢ですが/Girumasu_2.jpg", "examples/ギルドの受付嬢ですが/Girumasu_3.jpg"],
|
| 2833 |
-
0, 0,
|
| 2834 |
"PANORAMA", 0.6, 0.1, -1, False, "GAIN_BLOCKS",
|
| 2835 |
True, False, -1,
|
| 2836 |
"Affine_Partial", "Linear", True, 5000, 0.65, 5.0, 0.5, 10000, 10000, 15, 4,
|
|
@@ -2838,7 +2909,7 @@ with gr.Blocks() as demo:
|
|
| 2838 |
],
|
| 2839 |
[
|
| 2840 |
["examples/photographs1/img1.jpg", "examples/photographs1/img2.jpg", "examples/photographs1/img3.jpg", "examples/photographs1/img4.jpg"],
|
| 2841 |
-
0, 0,
|
| 2842 |
"PANORAMA", 0.6, 0.1, -1, True, "GAIN_BLOCKS",
|
| 2843 |
True, False, -1,
|
| 2844 |
"Homography", "Linear", True, 5000, 0.5, 5.0, 0.5, 10000, 10000, 15, 4,
|
|
|
|
| 1489 |
|
| 1490 |
# --- Function for N-Image Stitching (Primarily for Image List Input) ---
|
| 1491 |
def stitch_multiple_images(images, # List of NumPy images (BGR/BGRA, potentially pre-cropped)
|
| 1492 |
+
use_transparency=True,
|
| 1493 |
stitcher_mode_str="SCANS",
|
| 1494 |
registration_resol=0.6,
|
| 1495 |
seam_estimation_resol=0.1,
|
|
|
|
| 1510 |
max_blending_height=10000,
|
| 1511 |
blend_smooth_ksize=15,
|
| 1512 |
num_blend_levels=4,
|
| 1513 |
+
fixed_base_image_index=-1,
|
| 1514 |
):
|
| 1515 |
"""
|
| 1516 |
Stitches a list of images. Tries cv2.Stitcher first (unless 'DIRECT_PAIRWISE'),
|
| 1517 |
otherwise falls back to manual pairwise stitching.
|
| 1518 |
Returns ONE stitched image (RGB/RGBA) and log.
|
| 1519 |
+
Input images should be in BGR or BGRA format (already potentially cropped by caller).
|
| 1520 |
Output is RGBA. The 'enable_cropping' param here refers to final black border cropping.
|
| 1521 |
+
If use_transparency is False, the final output will be RGB (opaque background).
|
| 1522 |
"""
|
| 1523 |
log = log_and_print(f"--- Starting Stitching Process for {len(images)} Provided Images ---\n", "")
|
| 1524 |
total_start_time = time.time()
|
|
|
|
| 1798 |
|
| 1799 |
# Clean up the input image list now that it's processed
|
| 1800 |
del images
|
| 1801 |
+
if 'valid_images' in locals():
|
| 1802 |
+
del valid_images # Should be same as images now
|
| 1803 |
gc.collect()
|
| 1804 |
|
| 1805 |
# 3. Final Result Check and Return (Handling Alpha Channel)
|
|
|
|
| 1809 |
if stitched_img_bgra is not None and stitched_img_bgra.size > 0:
|
| 1810 |
log = log_and_print("Stitching process finished for image list.", log)
|
| 1811 |
try:
|
| 1812 |
+
# Handle final output based on transparency flag
|
| 1813 |
+
if use_transparency:
|
| 1814 |
+
# Preserve/Ensure RGBA
|
| 1815 |
+
if stitched_img_bgra.shape[2] == 4:
|
| 1816 |
# Convert BGRA to RGBA
|
| 1817 |
+
stitched_img_rgba = cv2.cvtColor(stitched_img_bgra, cv2.COLOR_BGRA2RGBA)
|
| 1818 |
+
log = log_and_print("Converted BGRA to RGBA (Transparency preserved).", log)
|
| 1819 |
+
else:
|
| 1820 |
+
# Source was BGR, make it RGBA (solid alpha)
|
| 1821 |
+
stitched_img_rgba = cv2.cvtColor(stitched_img_bgra, cv2.COLOR_BGR2RGBA)
|
| 1822 |
+
log = log_and_print("Converted BGR to RGBA.", log)
|
| 1823 |
else:
|
| 1824 |
+
# Force RGB (Drop Alpha / Opaque)
|
| 1825 |
+
if stitched_img_bgra.shape[2] == 4:
|
| 1826 |
+
stitched_img_rgba = cv2.cvtColor(stitched_img_bgra, cv2.COLOR_BGRA2RGB)
|
| 1827 |
+
log = log_and_print("Converted BGRA to RGB (Transparency disabled, alpha dropped).", log)
|
| 1828 |
+
else:
|
| 1829 |
+
# Convert BGR to RGB
|
| 1830 |
+
stitched_img_rgba = cv2.cvtColor(stitched_img_bgra, cv2.COLOR_BGR2RGB)
|
| 1831 |
+
log = log_and_print("Converted BGR to RGB.", log)
|
| 1832 |
|
| 1833 |
del stitched_img_bgra # Release BGRA version
|
| 1834 |
gc.collect()
|
|
|
|
| 1848 |
|
| 1849 |
# --- Video Frame Stitching ---
|
| 1850 |
def stitch_video_frames(video_path,
|
| 1851 |
+
use_transparency=True,
|
| 1852 |
crop_top_percent=0.0,
|
| 1853 |
crop_bottom_percent=0.0,
|
| 1854 |
enable_cropping=True, # This is for POST-stitch cropping
|
|
|
|
| 1869 |
sample_interval_ms=3000,
|
| 1870 |
max_composite_width=10000,
|
| 1871 |
max_composite_height=10000,
|
| 1872 |
+
progress=None,
|
| 1873 |
+
):
|
| 1874 |
"""
|
| 1875 |
Reads a video, samples frames, and stitches them sequentially.
|
| 1876 |
+
Returns a list of stitched images (RGBA if transparency=True, else RGB) and a log.
|
| 1877 |
"""
|
| 1878 |
log = log_and_print(f"--- Starting Incremental Video Stitching: {os.path.basename(video_path)} ---\n", "")
|
| 1879 |
log = log_and_print(f"Params: Interval={sample_interval_ms}ms, Transform={transform_model_str}, ORB={orb_nfeatures}, Ratio={match_ratio_thresh}\n", log)
|
|
|
|
| 1883 |
log = log_and_print(f"Post-Crop Black Borders: {enable_cropping}, Strict Edges: {strict_no_black_edges}\n", log)
|
| 1884 |
log = log_and_print(f"Blending: Method={blend_method}, GainComp={enable_gain_compensation}, SmoothKSize={blend_smooth_ksize}, MB Levels={num_blend_levels}\n", log)
|
| 1885 |
total_start_time = time.time()
|
| 1886 |
+
stitched_results_rgba = [] # Store final images (RGBA or RGB)
|
| 1887 |
|
| 1888 |
cap = cv2.VideoCapture(video_path)
|
| 1889 |
if not cap.isOpened():
|
|
|
|
| 1916 |
# Helper to save image to results list with correct color conversion
|
| 1917 |
def append_result(img_bgr_or_bgra):
|
| 1918 |
try:
|
| 1919 |
+
if use_transparency:
|
| 1920 |
+
if img_bgr_or_bgra.shape[2] == 4:
|
| 1921 |
+
stitched_results_rgba.append(cv2.cvtColor(img_bgr_or_bgra, cv2.COLOR_BGRA2RGBA))
|
| 1922 |
+
else:
|
| 1923 |
+
stitched_results_rgba.append(cv2.cvtColor(img_bgr_or_bgra, cv2.COLOR_BGR2RGBA))
|
| 1924 |
else:
|
| 1925 |
+
# Force RGB Output
|
| 1926 |
+
if img_bgr_or_bgra.shape[2] == 4:
|
| 1927 |
+
stitched_results_rgba.append(cv2.cvtColor(img_bgr_or_bgra, cv2.COLOR_BGRA2RGB))
|
| 1928 |
+
else:
|
| 1929 |
+
stitched_results_rgba.append(cv2.cvtColor(img_bgr_or_bgra, cv2.COLOR_BGR2RGB))
|
| 1930 |
return True
|
| 1931 |
except Exception as e:
|
| 1932 |
print(f"Error converting result: {e}")
|
|
|
|
| 1948 |
if frame_bgr_raw is not None and frame_bgr_raw.size > 0:
|
| 1949 |
processed_sampled_count += 1
|
| 1950 |
frame_bgra = None # Initialize BGR frame variable
|
| 1951 |
+
|
| 1952 |
+
# Handle Transparency Input
|
| 1953 |
+
if not use_transparency:
|
| 1954 |
+
# If transparency is disabled, ensure we treat the input as Opaque BGRA
|
| 1955 |
+
# We must use BGRA for the internal stitcher to work (warping masks),
|
| 1956 |
+
# but we ensure the Alpha channel is full (255).
|
| 1957 |
+
if frame_bgr_raw.ndim == 3 and frame_bgr_raw.shape[2] == 3:
|
| 1958 |
+
frame_bgra = cv2.cvtColor(frame_bgr_raw, cv2.COLOR_BGR2BGRA)
|
| 1959 |
+
elif frame_bgr_raw.ndim == 3 and frame_bgr_raw.shape[2] == 4:
|
| 1960 |
+
# Drop existing alpha and replace with opaque
|
| 1961 |
+
temp_bgr = cv2.cvtColor(frame_bgr_raw, cv2.COLOR_BGRA2BGR)
|
| 1962 |
+
frame_bgra = cv2.cvtColor(temp_bgr, cv2.COLOR_BGR2BGRA)
|
| 1963 |
+
del temp_bgr
|
| 1964 |
+
else:
|
| 1965 |
+
# Grayscale
|
| 1966 |
+
frame_bgra = cv2.cvtColor(frame_bgr_raw, cv2.COLOR_GRAY2BGRA)
|
| 1967 |
else:
|
| 1968 |
+
# Standard Transparency Handling
|
| 1969 |
+
if frame_bgr_raw.ndim == 2:
|
| 1970 |
+
frame_bgra = cv2.cvtColor(frame_bgr_raw, cv2.COLOR_GRAY2BGRA)
|
| 1971 |
+
elif frame_bgr_raw.ndim == 3 and frame_bgr_raw.shape[2] == 3:
|
| 1972 |
+
# Add alpha channel (opaque)
|
| 1973 |
+
frame_bgra = cv2.cvtColor(frame_bgr_raw, cv2.COLOR_BGR2BGRA)
|
| 1974 |
+
elif frame_bgr_raw.ndim == 3 and frame_bgr_raw.shape[2] == 4:
|
| 1975 |
+
frame_bgra = frame_bgr_raw
|
| 1976 |
+
else:
|
| 1977 |
+
log = log_and_print(f"Warning: Skipping frame {frame_num} due to unexpected shape {frame_bgr_raw.shape}\n", log)
|
| 1978 |
+
if frame_bgr_raw is not None:
|
| 1979 |
+
del frame_bgr_raw # Clean up original frame
|
| 1980 |
+
gc.collect()
|
| 1981 |
+
frame_num += 1
|
| 1982 |
+
continue # Skip to next frame read
|
| 1983 |
|
| 1984 |
# Release the raw frame once converted/checked (if a copy was made)
|
| 1985 |
+
if frame_bgra is not frame_bgr_raw and frame_bgr_raw is not None:
|
| 1986 |
del frame_bgr_raw
|
| 1987 |
frame_bgr_raw = None # Mark as deleted
|
| 1988 |
gc.collect()
|
|
|
|
| 2285 |
|
| 2286 |
# --- Gradio Interface Function ---
|
| 2287 |
def run_stitching_interface(input_files,
|
| 2288 |
+
use_transparency,
|
| 2289 |
crop_top_percent,
|
| 2290 |
crop_bottom_percent,
|
| 2291 |
stitcher_mode_str, # For cv2.Stitcher
|
|
|
|
| 2453 |
|
| 2454 |
final_stitched_images_rgba, stitch_log = stitch_video_frames(
|
| 2455 |
video_path,
|
| 2456 |
+
use_transparency=use_transparency,
|
| 2457 |
crop_top_percent=crop_top_percent,
|
| 2458 |
crop_bottom_percent=crop_bottom_percent,
|
| 2459 |
enable_cropping=enable_cropping, # Post-stitch crop
|
|
|
|
| 2486 |
try:
|
| 2487 |
n = np.fromfile(img_path, np.uint8)
|
| 2488 |
if n.size > 0:
|
| 2489 |
+
# Load logic based on transparency flag
|
| 2490 |
+
if use_transparency:
|
| 2491 |
# Use IMREAD_UNCHANGED to keep Alpha
|
| 2492 |
img = cv2.imdecode(n, cv2.IMREAD_UNCHANGED)
|
| 2493 |
+
else:
|
| 2494 |
+
img = cv2.imdecode(n, cv2.IMREAD_COLOR) # Ignore alpha
|
| 2495 |
else:
|
| 2496 |
+
log = log_and_print(f"Error: File is empty: {os.path.basename(img_path)}. Skipping.\n", log)
|
| 2497 |
+
continue
|
| 2498 |
+
|
| 2499 |
if img is None:
|
| 2500 |
raise ValueError("imdecode returned None")
|
| 2501 |
except Exception as e_read:
|
|
|
|
| 2504 |
del img
|
| 2505 |
continue # Skip to the next image
|
| 2506 |
|
| 2507 |
+
# Convert to BGRA for internal processing consistency
|
| 2508 |
+
# (Internal stitching needs masks, so we use BGRA format even if opaque)
|
| 2509 |
img_bgra = None
|
| 2510 |
try:
|
| 2511 |
+
if use_transparency:
|
| 2512 |
+
if img.ndim == 2:
|
| 2513 |
+
img_bgra = cv2.cvtColor(img, cv2.COLOR_GRAY2BGRA)
|
| 2514 |
+
elif img.ndim == 3 and img.shape[2] == 3:
|
| 2515 |
+
img_bgra = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
|
| 2516 |
+
elif img.ndim == 3 and img.shape[2] == 4:
|
| 2517 |
+
img_bgra = img # Already BGRA
|
| 2518 |
+
else:
|
| 2519 |
+
log = log_and_print(f"Error: Invalid image shape {img.shape} for {os.path.basename(img_path)}. Skipping.\n", log)
|
| 2520 |
+
del img
|
| 2521 |
+
if 'img_bgra' in locals() and img_bgra is not None:
|
| 2522 |
+
del img_bgra
|
| 2523 |
+
gc.collect()
|
| 2524 |
+
continue # Skip to the next image
|
| 2525 |
else:
|
| 2526 |
+
# Force Opaque BGRA
|
| 2527 |
+
if img.ndim == 2:
|
| 2528 |
+
img_bgra = cv2.cvtColor(img, cv2.COLOR_GRAY2BGRA)
|
| 2529 |
+
elif img.ndim == 3 and img.shape[2] == 3:
|
| 2530 |
+
img_bgra = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
|
| 2531 |
+
elif img.ndim == 3 and img.shape[2] == 4:
|
| 2532 |
+
# Drop alpha, re-add opaque
|
| 2533 |
+
tmp = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
|
| 2534 |
+
img_bgra = cv2.cvtColor(tmp, cv2.COLOR_BGR2BGRA)
|
| 2535 |
+
del tmp
|
| 2536 |
+
|
| 2537 |
except cv2.error as e_cvt_color:
|
| 2538 |
log = log_and_print(f"Error converting image color for {os.path.basename(img_path)}: {e_cvt_color}. Skipping.\n", log)
|
| 2539 |
del img
|
|
|
|
| 2576 |
|
| 2577 |
# Call the modified stitch_multiple_images function
|
| 2578 |
stitched_single_rgba, stitch_log_img = stitch_multiple_images(
|
| 2579 |
+
images_bgr_cropped, # Pass the list of cropped images (BGRA/BGR)
|
| 2580 |
+
use_transparency=use_transparency,
|
| 2581 |
stitcher_mode_str=stitcher_mode_str,
|
| 2582 |
registration_resol=registration_resol,
|
| 2583 |
seam_estimation_resol=seam_estimation_resol,
|
|
|
|
| 2679 |
full_path = os.path.join(temp_dir, filename)
|
| 2680 |
img_bgra = None # Initialize for finally block
|
| 2681 |
try:
|
| 2682 |
+
if use_transparency:
|
| 2683 |
+
# Handle RGBA to BGRA for saving
|
| 2684 |
+
# The result coming from stitcher is in RGB(A) format
|
| 2685 |
+
if img_rgba.shape[2] == 4:
|
| 2686 |
+
img_bgra = cv2.cvtColor(img_rgba, cv2.COLOR_RGBA2BGRA)
|
| 2687 |
+
else:
|
| 2688 |
+
img_bgra = cv2.cvtColor(img_rgba, cv2.COLOR_RGB2BGR)
|
| 2689 |
else:
|
| 2690 |
+
# Transparency Disabled: Output should be RGB (saved as BGR)
|
| 2691 |
+
if img_rgba.shape[2] == 4:
|
| 2692 |
+
img_bgra = cv2.cvtColor(img_rgba, cv2.COLOR_RGBA2BGR) # Drop Alpha
|
| 2693 |
+
else:
|
| 2694 |
+
img_bgra = cv2.cvtColor(img_rgba, cv2.COLOR_RGB2BGR)
|
| 2695 |
|
| 2696 |
# Use imencode -> write pattern for better handling of paths/special chars
|
| 2697 |
is_success, buf = cv2.imencode('.png', img_bgra)
|
|
|
|
| 2753 |
|
| 2754 |
# --- Parameters Grouping ---
|
| 2755 |
with gr.Accordion("Preprocessing Settings", open=True):
|
| 2756 |
+
use_transparency = gr.Checkbox(value=True, label="Use Transparency",
|
| 2757 |
+
info="If Checked: Preserves alpha channel (RGBA). Unchecked: Treats images as opaque and outputs RGB (Black background for warped areas).")
|
| 2758 |
crop_top_percent = gr.Slider(0.0, 49.0, step=0.5, value=0.0, label="Crop Top %",
|
| 2759 |
info="Percentage of height to remove from the TOP of each image/frame BEFORE stitching.")
|
| 2760 |
crop_bottom_percent = gr.Slider(0.0, 49.0, step=0.5, value=0.0, label="Crop Bottom %",
|
|
|
|
| 2832 |
inputs=[
|
| 2833 |
input_files,
|
| 2834 |
# Preprocessing
|
| 2835 |
+
use_transparency,
|
| 2836 |
crop_top_percent,
|
| 2837 |
crop_bottom_percent,
|
| 2838 |
# OpenCV Stitcher (Image List)
|
|
|
|
| 2868 |
examples = [
|
| 2869 |
[
|
| 2870 |
["examples/Wetter-Panorama/Wetter-Panorama1[NIuO6hrFTrg].mp4"],
|
| 2871 |
+
True, 0, 20,
|
| 2872 |
"DIRECT_PAIRWISE", 0.6, 0.1, -1, False, "GAIN_BLOCKS",
|
| 2873 |
True, False, -1,
|
| 2874 |
"Homography", "Multi-Band", True, 5000, 0.5, 5.0, 0.5, 10000, 10000, 15, 4,
|
|
|
|
| 2876 |
],
|
| 2877 |
[
|
| 2878 |
["examples/Wetter-Panorama/Wetter-Panorama2[NIuO6hrFTrg].mp4"],
|
| 2879 |
+
True, 0, 20,
|
| 2880 |
"DIRECT_PAIRWISE", 0.6, 0.1, -1, False, "GAIN_BLOCKS",
|
| 2881 |
True, False, -1,
|
| 2882 |
"Homography", "Multi-Band", True, 5000, 0.5, 5.0, 0.5, 10000, 10000, 15, 4,
|
|
|
|
| 2885 |
[
|
| 2886 |
["examples/NieRAutomata/nier2B_01.jpg", "examples/NieRAutomata/nier2B_02.jpg", "examples/NieRAutomata/nier2B_03.jpg", "examples/NieRAutomata/nier2B_04.jpg", "examples/NieRAutomata/nier2B_05.jpg",
|
| 2887 |
"examples/NieRAutomata/nier2B_06.jpg", "examples/NieRAutomata/nier2B_07.jpg", "examples/NieRAutomata/nier2B_08.jpg", "examples/NieRAutomata/nier2B_09.jpg", "examples/NieRAutomata/nier2B_10.jpg", ],
|
| 2888 |
+
True, 0, 0,
|
| 2889 |
"PANORAMA", 0.6, 0.1, -1, False, "GAIN_BLOCKS",
|
| 2890 |
True, False, -1,
|
| 2891 |
"Homography", "Multi-Band", True, 5000, 0.5, 5.0, 0.5, 10000, 10000, 15, 4,
|
|
|
|
| 2893 |
],
|
| 2894 |
[
|
| 2895 |
["examples/cat/cat_left.jpg", "examples/cat/cat_right.jpg"],
|
| 2896 |
+
True, 0, 0,
|
| 2897 |
"SCANS", 0.6, 0.1, -1, False, "GAIN_BLOCKS",
|
| 2898 |
True, False, -1,
|
| 2899 |
"Affine_Partial", "Linear", True, 5000, 0.5, 5.0, 0.5, 10000, 10000, 15, 4,
|
|
|
|
| 2901 |
],
|
| 2902 |
[
|
| 2903 |
["examples/ギルドの受付嬢ですが/Girumasu_1.jpg", "examples/ギルドの受付嬢ですが/Girumasu_2.jpg", "examples/ギルドの受付嬢ですが/Girumasu_3.jpg"],
|
| 2904 |
+
True, 0, 0,
|
| 2905 |
"PANORAMA", 0.6, 0.1, -1, False, "GAIN_BLOCKS",
|
| 2906 |
True, False, -1,
|
| 2907 |
"Affine_Partial", "Linear", True, 5000, 0.65, 5.0, 0.5, 10000, 10000, 15, 4,
|
|
|
|
| 2909 |
],
|
| 2910 |
[
|
| 2911 |
["examples/photographs1/img1.jpg", "examples/photographs1/img2.jpg", "examples/photographs1/img3.jpg", "examples/photographs1/img4.jpg"],
|
| 2912 |
+
True, 0, 0,
|
| 2913 |
"PANORAMA", 0.6, 0.1, -1, True, "GAIN_BLOCKS",
|
| 2914 |
True, False, -1,
|
| 2915 |
"Homography", "Linear", True, 5000, 0.5, 5.0, 0.5, 10000, 10000, 15, 4,
|
webui.bat
CHANGED
|
@@ -1,21 +1,37 @@
|
|
| 1 |
@echo off
|
| 2 |
|
| 3 |
-
:: The source of the webui.bat file is stable-diffusion-webui
|
| 4 |
-
::
|
| 5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
if not defined PYTHON (set PYTHON=python)
|
| 7 |
-
if not defined
|
|
|
|
| 8 |
|
| 9 |
mkdir tmp 2>NUL
|
| 10 |
|
|
|
|
| 11 |
%PYTHON% -c "" >tmp/stdout.txt 2>tmp/stderr.txt
|
| 12 |
if %ERRORLEVEL% == 0 goto :check_pip
|
| 13 |
echo Couldn't launch python
|
| 14 |
goto :show_stdout_stderr
|
| 15 |
|
| 16 |
:check_pip
|
|
|
|
| 17 |
%PYTHON% -mpip --help >tmp/stdout.txt 2>tmp/stderr.txt
|
| 18 |
if %ERRORLEVEL% == 0 goto :start_venv
|
|
|
|
| 19 |
if "%PIP_INSTALLER_LOCATION%" == "" goto :show_stdout_stderr
|
| 20 |
%PYTHON% "%PIP_INSTALLER_LOCATION%" >tmp/stdout.txt 2>tmp/stderr.txt
|
| 21 |
if %ERRORLEVEL% == 0 goto :start_venv
|
|
@@ -23,33 +39,106 @@ echo Couldn't install pip
|
|
| 23 |
goto :show_stdout_stderr
|
| 24 |
|
| 25 |
:start_venv
|
| 26 |
-
if
|
| 27 |
-
if ["%
|
|
|
|
|
|
|
| 28 |
|
|
|
|
| 29 |
dir "%VENV_DIR%\Scripts\Python.exe" >tmp/stdout.txt 2>tmp/stderr.txt
|
| 30 |
-
if %ERRORLEVEL% == 0 goto :
|
| 31 |
|
|
|
|
|
|
|
| 32 |
for /f "delims=" %%i in ('CALL %PYTHON% -c "import sys; print(sys.executable)"') do set PYTHON_FULLNAME="%%i"
|
| 33 |
echo Creating venv in directory %VENV_DIR% using python %PYTHON_FULLNAME%
|
| 34 |
%PYTHON_FULLNAME% -m venv "%VENV_DIR%" >tmp/stdout.txt 2>tmp/stderr.txt
|
| 35 |
-
if %ERRORLEVEL%
|
| 36 |
-
echo Unable to create venv in directory "%VENV_DIR%"
|
| 37 |
-
goto :show_stdout_stderr
|
| 38 |
-
|
| 39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
set PYTHON="%VENV_DIR%\Scripts\Python.exe"
|
| 41 |
-
echo venv %PYTHON%
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
-
:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
goto :launch
|
| 45 |
|
| 46 |
:launch
|
| 47 |
-
|
|
|
|
|
|
|
|
|
|
| 48 |
pause
|
| 49 |
exit /b
|
| 50 |
|
| 51 |
-
:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
|
|
|
|
|
|
|
|
|
| 53 |
echo.
|
| 54 |
echo exit code: %errorlevel%
|
| 55 |
|
|
@@ -61,13 +150,13 @@ type tmp\stdout.txt
|
|
| 61 |
|
| 62 |
:show_stderr
|
| 63 |
for /f %%i in ("tmp\stderr.txt") do set size=%%~zi
|
| 64 |
-
if %size% equ 0 goto :
|
| 65 |
echo.
|
| 66 |
echo stderr:
|
| 67 |
type tmp\stderr.txt
|
| 68 |
|
| 69 |
:endofscript
|
| 70 |
-
|
| 71 |
echo.
|
| 72 |
echo Launch unsuccessful. Exiting.
|
| 73 |
pause
|
|
|
|
|
|
| 1 |
@echo off
|
| 2 |
|
| 3 |
+
:: The original source of the webui.bat file is stable-diffusion-webui
|
| 4 |
+
:: Modified and enhanced by Gemini with features for venv management and requirements handling.
|
| 5 |
|
| 6 |
+
:: --------- Configuration ---------
|
| 7 |
+
set COMMANDLINE_ARGS=
|
| 8 |
+
:: Define the name of the Launch application
|
| 9 |
+
set APPLICATION_NAME=app.py
|
| 10 |
+
:: Define the name of the virtual environment directory
|
| 11 |
+
set VENV_NAME=venv
|
| 12 |
+
:: Set to 1 to always attempt to update packages from requirements.txt on every launch
|
| 13 |
+
set ALWAYS_UPDATE_REQS=0
|
| 14 |
+
:: ---------------------------------
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
:: Set PYTHON executable if not already defined
|
| 18 |
if not defined PYTHON (set PYTHON=python)
|
| 19 |
+
:: Set VENV_DIR using VENV_NAME if not already defined
|
| 20 |
+
if not defined VENV_DIR (set "VENV_DIR=%~dp0%VENV_NAME%")
|
| 21 |
|
| 22 |
mkdir tmp 2>NUL
|
| 23 |
|
| 24 |
+
:: Check if Python is callable
|
| 25 |
%PYTHON% -c "" >tmp/stdout.txt 2>tmp/stderr.txt
|
| 26 |
if %ERRORLEVEL% == 0 goto :check_pip
|
| 27 |
echo Couldn't launch python
|
| 28 |
goto :show_stdout_stderr
|
| 29 |
|
| 30 |
:check_pip
|
| 31 |
+
:: Check if pip is available
|
| 32 |
%PYTHON% -mpip --help >tmp/stdout.txt 2>tmp/stderr.txt
|
| 33 |
if %ERRORLEVEL% == 0 goto :start_venv
|
| 34 |
+
:: If pip is not available and PIP_INSTALLER_LOCATION is set, try to install pip
|
| 35 |
if "%PIP_INSTALLER_LOCATION%" == "" goto :show_stdout_stderr
|
| 36 |
%PYTHON% "%PIP_INSTALLER_LOCATION%" >tmp/stdout.txt 2>tmp/stderr.txt
|
| 37 |
if %ERRORLEVEL% == 0 goto :start_venv
|
|
|
|
| 39 |
goto :show_stdout_stderr
|
| 40 |
|
| 41 |
:start_venv
|
| 42 |
+
:: Skip venv creation/activation if VENV_DIR is explicitly set to "-"
|
| 43 |
+
if ["%VENV_DIR%"] == ["-"] goto :skip_venv_entirely
|
| 44 |
+
:: Skip venv creation/activation if SKIP_VENV is set to "1"
|
| 45 |
+
if ["%SKIP_VENV%"] == ["1"] goto :skip_venv_entirely
|
| 46 |
|
| 47 |
+
:: Check if the venv already exists by looking for Python.exe in its Scripts directory
|
| 48 |
dir "%VENV_DIR%\Scripts\Python.exe" >tmp/stdout.txt 2>tmp/stderr.txt
|
| 49 |
+
if %ERRORLEVEL% == 0 goto :activate_venv_and_maybe_update
|
| 50 |
|
| 51 |
+
:: Venv does not exist, create it
|
| 52 |
+
echo Virtual environment not found in "%VENV_DIR%". Creating a new one.
|
| 53 |
for /f "delims=" %%i in ('CALL %PYTHON% -c "import sys; print(sys.executable)"') do set PYTHON_FULLNAME="%%i"
|
| 54 |
echo Creating venv in directory %VENV_DIR% using python %PYTHON_FULLNAME%
|
| 55 |
%PYTHON_FULLNAME% -m venv "%VENV_DIR%" >tmp/stdout.txt 2>tmp/stderr.txt
|
| 56 |
+
if %ERRORLEVEL% NEQ 0 (
|
| 57 |
+
echo Unable to create venv in directory "%VENV_DIR%"
|
| 58 |
+
goto :show_stdout_stderr
|
| 59 |
+
)
|
| 60 |
+
echo Venv created.
|
| 61 |
+
|
| 62 |
+
:: Install requirements for the first time if venv was just created
|
| 63 |
+
:: This section handles the initial installation of packages from requirements.txt
|
| 64 |
+
:: immediately after a new virtual environment is created.
|
| 65 |
+
echo Checking for requirements.txt for initial setup in %~dp0
|
| 66 |
+
if exist "%~dp0requirements.txt" (
|
| 67 |
+
echo Found requirements.txt, attempting to install for initial setup...
|
| 68 |
+
call "%VENV_DIR%\Scripts\activate.bat"
|
| 69 |
+
echo Installing packages from requirements.txt ^(initial setup^)...
|
| 70 |
+
"%VENV_DIR%\Scripts\python.exe" -m pip install -r "%~dp0requirements.txt"
|
| 71 |
+
if %ERRORLEVEL% NEQ 0 (
|
| 72 |
+
echo Failed to install requirements during initial setup. Please check the output above.
|
| 73 |
+
pause
|
| 74 |
+
goto :show_stdout_stderr_custom_pip_initial
|
| 75 |
+
)
|
| 76 |
+
echo Initial requirements installed successfully.
|
| 77 |
+
call "%VENV_DIR%\Scripts\deactivate.bat"
|
| 78 |
+
) else (
|
| 79 |
+
echo No requirements.txt found for initial setup, skipping package installation.
|
| 80 |
+
)
|
| 81 |
+
goto :activate_venv_and_maybe_update
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
:activate_venv_and_maybe_update
|
| 85 |
+
:: This label is reached if the venv exists or was just created.
|
| 86 |
+
:: Set PYTHON to point to the venv's Python interpreter.
|
| 87 |
set PYTHON="%VENV_DIR%\Scripts\Python.exe"
|
| 88 |
+
echo Activating venv: %PYTHON%
|
| 89 |
+
|
| 90 |
+
:: Always update requirements if ALWAYS_UPDATE_REQS is 1
|
| 91 |
+
:: This section allows for updating packages from requirements.txt on every launch
|
| 92 |
+
:: if the ALWAYS_UPDATE_REQS variable is set to 1.
|
| 93 |
+
if defined ALWAYS_UPDATE_REQS (
|
| 94 |
+
if "%ALWAYS_UPDATE_REQS%"=="1" (
|
| 95 |
+
echo ALWAYS_UPDATE_REQS is enabled.
|
| 96 |
+
if exist "%~dp0requirements.txt" (
|
| 97 |
+
echo Attempting to update packages from requirements.txt...
|
| 98 |
+
REM No need to call activate.bat here again, PYTHON is already set to the venv's python
|
| 99 |
+
%PYTHON% -m pip install -r "%~dp0requirements.txt"
|
| 100 |
+
if %ERRORLEVEL% NEQ 0 (
|
| 101 |
+
echo Failed to update requirements. Please check the output above.
|
| 102 |
+
pause
|
| 103 |
+
goto :endofscript
|
| 104 |
+
)
|
| 105 |
+
echo Requirements updated successfully.
|
| 106 |
+
) else (
|
| 107 |
+
echo ALWAYS_UPDATE_REQS is enabled, but no requirements.txt found. Skipping update.
|
| 108 |
+
)
|
| 109 |
+
) else (
|
| 110 |
+
echo ALWAYS_UPDATE_REQS is not enabled or not set to 1. Skipping routine update.
|
| 111 |
+
)
|
| 112 |
+
)
|
| 113 |
|
| 114 |
+
goto :launch
|
| 115 |
+
|
| 116 |
+
:skip_venv_entirely
|
| 117 |
+
:: This label is reached if venv usage is explicitly skipped.
|
| 118 |
+
echo Skipping venv.
|
| 119 |
goto :launch
|
| 120 |
|
| 121 |
:launch
|
| 122 |
+
:: Launch the main application
|
| 123 |
+
echo Launching Web UI with arguments: %COMMANDLINE_ARGS% %*
|
| 124 |
+
%PYTHON% %APPLICATION_NAME% %COMMANDLINE_ARGS% %*
|
| 125 |
+
echo Launch finished.
|
| 126 |
pause
|
| 127 |
exit /b
|
| 128 |
|
| 129 |
+
:show_stdout_stderr_custom_pip_initial
|
| 130 |
+
:: Custom error handler for failures during the initial pip install process.
|
| 131 |
+
echo.
|
| 132 |
+
echo exit code ^(pip initial install^): %errorlevel%
|
| 133 |
+
echo Errors during initial pip install. See output above.
|
| 134 |
+
echo.
|
| 135 |
+
echo Launch unsuccessful. Exiting.
|
| 136 |
+
pause
|
| 137 |
+
exit /b
|
| 138 |
|
| 139 |
+
|
| 140 |
+
:show_stdout_stderr
|
| 141 |
+
:: General error handler: displays stdout and stderr from the tmp directory.
|
| 142 |
echo.
|
| 143 |
echo exit code: %errorlevel%
|
| 144 |
|
|
|
|
| 150 |
|
| 151 |
:show_stderr
|
| 152 |
for /f %%i in ("tmp\stderr.txt") do set size=%%~zi
|
| 153 |
+
if %size% equ 0 goto :endofscript
|
| 154 |
echo.
|
| 155 |
echo stderr:
|
| 156 |
type tmp\stderr.txt
|
| 157 |
|
| 158 |
:endofscript
|
|
|
|
| 159 |
echo.
|
| 160 |
echo Launch unsuccessful. Exiting.
|
| 161 |
pause
|
| 162 |
+
exit /b
|