Spaces:
				
			
			
	
			
			
		Runtime error
		
	
	
	
			
			
	
	
	
	
		
		
		Runtime error
		
	Upload 4 files
Browse files- app.py +232 -0
- config.py +22 -0
- create_mask.py +84 -0
- inpaint.py +121 -0
    	
        app.py
    ADDED
    
    | @@ -0,0 +1,232 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import gradio as gr
         | 
| 2 | 
            +
            import numpy as np
         | 
| 3 | 
            +
            import imageio
         | 
| 4 | 
            +
            import cv2
         | 
| 5 | 
            +
            import numpy as np
         | 
| 6 | 
            +
            from inpaint import InpaintingTester
         | 
| 7 | 
            +
            import os 
         | 
| 8 | 
            +
            import shutil
         | 
| 9 | 
            +
            import re 
         | 
| 10 | 
            +
            import uuid
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            def create_mask(watermark, mask_type="white"):
         | 
| 13 | 
            +
                """
         | 
| 14 | 
            +
                Create a mask for the watermark region.
         | 
| 15 | 
            +
                mask_type: 'white' for white mask and 'black' for black mask
         | 
| 16 | 
            +
                """
         | 
| 17 | 
            +
                h, w, _ = watermark.shape
         | 
| 18 | 
            +
                if mask_type == "white":
         | 
| 19 | 
            +
                    return np.ones((h, w), dtype=np.uint8) * 255  # White mask
         | 
| 20 | 
            +
                elif mask_type == "black":
         | 
| 21 | 
            +
                    return np.zeros((h, w), dtype=np.uint8)  # Black mask
         | 
| 22 | 
            +
                return None
         | 
| 23 | 
            +
             | 
| 24 | 
            +
             | 
| 25 | 
            +
            def inpaint_watermark(watermark, mask):
         | 
| 26 | 
            +
                """Inpaint the watermark region using the mask."""
         | 
| 27 | 
            +
                return cv2.inpaint(watermark, mask, inpaintRadius=3, flags=cv2.INPAINT_TELEA)
         | 
| 28 | 
            +
             | 
| 29 | 
            +
             | 
| 30 | 
            +
            def place_inpainted_back(image, inpainted_region, location):
         | 
| 31 | 
            +
                """Place the inpainted region back into the original image."""
         | 
| 32 | 
            +
                x_start, y_start, x_end, y_end = location
         | 
| 33 | 
            +
                image[y_start:y_end, x_start:x_end] = inpainted_region
         | 
| 34 | 
            +
                return image
         | 
| 35 | 
            +
             | 
| 36 | 
            +
             | 
| 37 | 
            +
            def extract_watermark(image, height_ratio=0.15, width_ratio=0.15, margin=0):
         | 
| 38 | 
            +
                """Extract watermark from the image using given ratios and margin."""
         | 
| 39 | 
            +
                h, w, _ = image.shape
         | 
| 40 | 
            +
                crop_h, crop_w = int(h * height_ratio), int(w * width_ratio)
         | 
| 41 | 
            +
                x_start, y_start = w - crop_w, h - crop_h
         | 
| 42 | 
            +
                watermark = image[y_start:h-margin, x_start:w-margin]
         | 
| 43 | 
            +
                location = (x_start, y_start, w-margin, h-margin)
         | 
| 44 | 
            +
                return watermark, location
         | 
| 45 | 
            +
             | 
| 46 | 
            +
             | 
| 47 | 
            +
            def load_inpainting_model():
         | 
| 48 | 
            +
                """Load the inpainting model."""
         | 
| 49 | 
            +
                save_path = "./output"
         | 
| 50 | 
            +
                # resize_to = None  # Default size from config
         | 
| 51 | 
            +
                resize_to = (480,480)
         | 
| 52 | 
            +
                return InpaintingTester(save_path, resize_to)
         | 
| 53 | 
            +
             | 
| 54 | 
            +
             | 
| 55 | 
            +
            def process_image_with_model(image_path, mask_path, tester):
         | 
| 56 | 
            +
                """Process the image using the inpainting model and return the cleaned image path."""
         | 
| 57 | 
            +
                image_mask_pairs = [(image_path, mask_path)]
         | 
| 58 | 
            +
                return tester.process_multiple_images(image_mask_pairs)[0]
         | 
| 59 | 
            +
             | 
| 60 | 
            +
             | 
| 61 | 
            +
             | 
| 62 | 
            +
             | 
| 63 | 
            +
             | 
| 64 | 
            +
            def img_file_name(image_path):
         | 
| 65 | 
            +
                global image_folder
         | 
| 66 | 
            +
                text=os.path.basename(image_path)
         | 
| 67 | 
            +
                text=text.split(".")[0]
         | 
| 68 | 
            +
                # Remove all non-alphabetic characters and convert to lowercase
         | 
| 69 | 
            +
                text = re.sub(r'[^a-zA-Z\s]', '', text)  # Retain only alphabets and spaces
         | 
| 70 | 
            +
                text = text.lower().strip()             # Convert to lowercase and strip leading/trailing spaces
         | 
| 71 | 
            +
                text = text.replace(" ", "_")           # Replace spaces with underscores
         | 
| 72 | 
            +
                
         | 
| 73 | 
            +
                # Truncate or handle empty text
         | 
| 74 | 
            +
                truncated_text = text[:25] if len(text) > 25 else text if len(text) > 0 else "empty"
         | 
| 75 | 
            +
                
         | 
| 76 | 
            +
                # Generate a random string for uniqueness
         | 
| 77 | 
            +
                random_string = uuid.uuid4().hex[:8].upper()
         | 
| 78 | 
            +
                
         | 
| 79 | 
            +
                # Construct the file name
         | 
| 80 | 
            +
                file_name = f"{image_folder}/{truncated_text}_{random_string}.png"
         | 
| 81 | 
            +
                return file_name
         | 
| 82 | 
            +
                
         | 
| 83 | 
            +
            def logo_remover(image_path):
         | 
| 84 | 
            +
                image = cv2.imread(image_path)
         | 
| 85 | 
            +
                image = cv2.resize(image, (1280, 1280))  # Resize image if needed
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                # Extract watermark and location
         | 
| 88 | 
            +
                first_crop, first_location = extract_watermark(image, 0.50, 0.50, 0)
         | 
| 89 | 
            +
                watermark, location = extract_watermark(first_crop, 0.12, 0.26, 27) #height, side, margin
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                
         | 
| 92 | 
            +
                # Create black and white masks
         | 
| 93 | 
            +
                mask1 = create_mask(first_crop, "black")
         | 
| 94 | 
            +
                mask2 = create_mask(watermark, "white")
         | 
| 95 | 
            +
                combined_mask = place_inpainted_back(mask1, mask2, location)
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                # Save temporary files
         | 
| 98 | 
            +
                input_image = "./input/temp.png"
         | 
| 99 | 
            +
                input_mask = "./input/temp_mask.png"
         | 
| 100 | 
            +
                # temp_image = cv2.resize(first_crop, (512, 512))
         | 
| 101 | 
            +
                temp_image=first_crop
         | 
| 102 | 
            +
                cv2.imwrite(input_image, temp_image)
         | 
| 103 | 
            +
                # temp_mask = cv2.resize(combined_mask, (512, 512))
         | 
| 104 | 
            +
                temp_mask=combined_mask
         | 
| 105 | 
            +
                cv2.imwrite(input_mask, temp_mask)
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                
         | 
| 108 | 
            +
                clean_image_path = process_image_with_model(input_image, input_mask, tester)
         | 
| 109 | 
            +
                
         | 
| 110 | 
            +
                # Check if the image was loaded correctly
         | 
| 111 | 
            +
                if clean_image_path is None:
         | 
| 112 | 
            +
                    print(f"Failed to load image: {clean_image_path}")
         | 
| 113 | 
            +
                    return  # Or handle the error accordingly
         | 
| 114 | 
            +
                clean_image = cv2.imread(clean_image_path)
         | 
| 115 | 
            +
                clean_image = cv2.resize(clean_image, (combined_mask.shape[1], combined_mask.shape[0]))
         | 
| 116 | 
            +
                result_image = place_inpainted_back(image, clean_image, first_location)
         | 
| 117 | 
            +
                save_path=img_file_name(image_path)
         | 
| 118 | 
            +
                cv2.imwrite(save_path, result_image)
         | 
| 119 | 
            +
                return save_path
         | 
| 120 | 
            +
             | 
| 121 | 
            +
             | 
| 122 | 
            +
             | 
| 123 | 
            +
             | 
| 124 | 
            +
             | 
| 125 | 
            +
            # Define a function to handle the image editing and return the final result
         | 
| 126 | 
            +
            def process_and_return(im):
         | 
| 127 | 
            +
                global tester
         | 
| 128 | 
            +
                # Save the composite image (base image) and mask to files
         | 
| 129 | 
            +
                base_image_path = "base_image.png"
         | 
| 130 | 
            +
                mask_image_path = "mask_image.png"
         | 
| 131 | 
            +
                
         | 
| 132 | 
            +
                # Save the composite image (base image)
         | 
| 133 | 
            +
                imageio.imwrite(base_image_path, im["composite"])
         | 
| 134 | 
            +
                
         | 
| 135 | 
            +
                # Extract the alpha channel (mask)
         | 
| 136 | 
            +
                alpha_channel = im["layers"][0][:, :, 3]
         | 
| 137 | 
            +
                
         | 
| 138 | 
            +
                # Create the mask: white (255) where drawn, black (0) elsewhere
         | 
| 139 | 
            +
                mask = np.zeros_like(alpha_channel, dtype=np.uint8)
         | 
| 140 | 
            +
                mask[alpha_channel > 0] = 255  # Set drawn areas to white (255)
         | 
| 141 | 
            +
                
         | 
| 142 | 
            +
                # Save the mask image
         | 
| 143 | 
            +
                imageio.imwrite(mask_image_path, mask)
         | 
| 144 | 
            +
                # Process the images using the inpainting model
         | 
| 145 | 
            +
                final_result = process_image_with_model(base_image_path, mask_image_path,tester)
         | 
| 146 | 
            +
                
         | 
| 147 | 
            +
                # Return the processed image
         | 
| 148 | 
            +
                return final_result
         | 
| 149 | 
            +
             | 
| 150 | 
            +
            def ui_3():
         | 
| 151 | 
            +
                # Create a Gradio app
         | 
| 152 | 
            +
                with gr.Blocks() as demo:
         | 
| 153 | 
            +
                    with gr.Row():
         | 
| 154 | 
            +
                        # Create an ImageEditor component for uploading and editing the image
         | 
| 155 | 
            +
                        im = gr.ImageEditor(
         | 
| 156 | 
            +
                            type="numpy",
         | 
| 157 | 
            +
                            canvas_size=(1, 1),  # Use canvas_size instead of crop_size
         | 
| 158 | 
            +
                            layers=True,  # Allow layers in the editor
         | 
| 159 | 
            +
                            transforms=["crop"],  # Allow cropping
         | 
| 160 | 
            +
                            format="png",  # Save images in PNG format
         | 
| 161 | 
            +
                            label="Base Image",
         | 
| 162 | 
            +
                            show_label=True
         | 
| 163 | 
            +
                        )
         | 
| 164 | 
            +
                        # Create an Image component to display the processed result
         | 
| 165 | 
            +
                        im2 = gr.Image(label="Processed Image", show_label=True)
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                    # Create a Button to trigger the image processing
         | 
| 168 | 
            +
                    btn = gr.Button("Process Image")
         | 
| 169 | 
            +
                    
         | 
| 170 | 
            +
                    # Define an event listener to trigger the image processing when the button is clicked
         | 
| 171 | 
            +
                    btn.click(process_and_return, inputs=im, outputs=im2)  # Output processed image
         | 
| 172 | 
            +
                return demo
         | 
| 173 | 
            +
            # def handle_pil_image(image):
         | 
| 174 | 
            +
                
         | 
| 175 | 
            +
            #     logo_remover(image)
         | 
| 176 | 
            +
                
         | 
| 177 | 
            +
             | 
| 178 | 
            +
            def ui_1():
         | 
| 179 | 
            +
                test_examples=[["./input/image.jpg"]]
         | 
| 180 | 
            +
                gradio_input=[gr.Image(label='Upload an Image',type="filepath")]
         | 
| 181 | 
            +
                gradio_Output=[gr.Image(label='Display Image')]
         | 
| 182 | 
            +
                gradio_interface = gr.Interface(fn=logo_remover, inputs=gradio_input,outputs=gradio_Output ,
         | 
| 183 | 
            +
                                            title="Meta Watermark Remover For Image",
         | 
| 184 | 
            +
                                            examples=test_examples)
         | 
| 185 | 
            +
                return gradio_interface
         | 
| 186 | 
            +
            from PIL import Image
         | 
| 187 | 
            +
            import zipfile
         | 
| 188 | 
            +
             | 
| 189 | 
            +
            def make_zip(image_list):
         | 
| 190 | 
            +
                zip_path = f"./temp/images/{uuid.uuid4().hex[:6]}.zip"
         | 
| 191 | 
            +
                with zipfile.ZipFile(zip_path, 'w') as zipf:
         | 
| 192 | 
            +
                    for image in image_list:
         | 
| 193 | 
            +
                        zipf.write(image, os.path.basename(image))
         | 
| 194 | 
            +
                return zip_path
         | 
| 195 | 
            +
             | 
| 196 | 
            +
            def handle_multiple_files(image_files):
         | 
| 197 | 
            +
                image_list = []
         | 
| 198 | 
            +
                if len(image_files) == 1:
         | 
| 199 | 
            +
                    saved_path=logo_remover(image_files[0])
         | 
| 200 | 
            +
                    return saved_path
         | 
| 201 | 
            +
                else:
         | 
| 202 | 
            +
                    for image_path in image_files:
         | 
| 203 | 
            +
                        saved_path=logo_remover(image_path)
         | 
| 204 | 
            +
                        image_list.append(saved_path)
         | 
| 205 | 
            +
                    zip_path = make_zip(image_list)
         | 
| 206 | 
            +
                    return zip_path
         | 
| 207 | 
            +
                
         | 
| 208 | 
            +
             | 
| 209 | 
            +
                
         | 
| 210 | 
            +
            def ui_2():
         | 
| 211 | 
            +
                gradio_multiple_images = gr.Interface(
         | 
| 212 | 
            +
                handle_multiple_files,
         | 
| 213 | 
            +
                [gr.File(type='filepath', file_count='multiple',label='Upload Images')],
         | 
| 214 | 
            +
                [gr.File(label='Download File')],
         | 
| 215 | 
            +
                title='Meta Watermark Remover For Bulk Images',
         | 
| 216 | 
            +
                cache_examples=True
         | 
| 217 | 
            +
                )
         | 
| 218 | 
            +
                return gradio_multiple_images
         | 
| 219 | 
            +
             | 
| 220 | 
            +
            # Load and process the inpainting model
         | 
| 221 | 
            +
            tester = load_inpainting_model()
         | 
| 222 | 
            +
            image_folder="./temp/images"
         | 
| 223 | 
            +
            if not os.path.exists(image_folder):
         | 
| 224 | 
            +
                os.makedirs(image_folder)
         | 
| 225 | 
            +
                
         | 
| 226 | 
            +
            # Launch the Gradio app
         | 
| 227 | 
            +
            if __name__ == "__main__":
         | 
| 228 | 
            +
                demo2 = ui_1()
         | 
| 229 | 
            +
                demo3 = ui_2()
         | 
| 230 | 
            +
                demo1=ui_3()
         | 
| 231 | 
            +
                demo=gr.TabbedInterface([demo1,demo2,demo3], title="Meta Watermark Remover",tab_names=["Manual Remove","Meta Single Image","Meta Bulk Images"])
         | 
| 232 | 
            +
                demo.launch(show_error=True)
         | 
    	
        config.py
    ADDED
    
    | @@ -0,0 +1,22 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import torch
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # GENERIC
         | 
| 4 | 
            +
            GPU_DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
         | 
| 5 | 
            +
            INIMAGE = "./input/image.jpg"
         | 
| 6 | 
            +
            MASKIMAGE = "./input/mask.jpg"
         | 
| 7 | 
            +
            OUTIMAGE = "./output/inpainted_img.png"
         | 
| 8 | 
            +
            RESIZE_TO = (512, 512)
         | 
| 9 | 
            +
            CUDA = True if torch.cuda.is_available() else False
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            # DEEPFILLv2
         | 
| 12 | 
            +
            DEEPFILL_MODEL_PATH = "./model/deepfillv2_WGAN.pth"
         | 
| 13 | 
            +
            GPU_ID = -1
         | 
| 14 | 
            +
            INIT_TYPE = "xavier"
         | 
| 15 | 
            +
            INIT_GAIN = 0.02
         | 
| 16 | 
            +
            PAD_TYPE = "zero"
         | 
| 17 | 
            +
            IN_CHANNELS = 4
         | 
| 18 | 
            +
            OUT_CHANNELS = 3
         | 
| 19 | 
            +
            LATENT_CHANNELS = 48
         | 
| 20 | 
            +
            ACTIVATION = "elu"
         | 
| 21 | 
            +
            NORM = "in"
         | 
| 22 | 
            +
            NUM_WORKERS = 0
         | 
    	
        create_mask.py
    ADDED
    
    | @@ -0,0 +1,84 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import numpy as np
         | 
| 2 | 
            +
            import cv2
         | 
| 3 | 
            +
            from config import RESIZE_TO, MASKIMAGE
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            # image mask
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            # free form mask
         | 
| 8 | 
            +
            # bbox mask
         | 
| 9 | 
            +
             | 
| 10 | 
            +
             | 
| 11 | 
            +
            def create_ff_mask():
         | 
| 12 | 
            +
                config = {
         | 
| 13 | 
            +
                    "img_shape": list(RESIZE_TO),
         | 
| 14 | 
            +
                    "mv": 15,
         | 
| 15 | 
            +
                    "ma": 4.0,
         | 
| 16 | 
            +
                    "ml": 40,
         | 
| 17 | 
            +
                    "mbw": 5,
         | 
| 18 | 
            +
                }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                h, w = config["img_shape"]
         | 
| 21 | 
            +
                mask = np.zeros((h, w))
         | 
| 22 | 
            +
                num_v = np.random.randint(config["mv"])
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                for i in range(num_v):
         | 
| 25 | 
            +
                    start_x = np.random.randint(w)
         | 
| 26 | 
            +
                    start_y = np.random.randint(h)
         | 
| 27 | 
            +
                    for j in range(1 + np.random.randint(5)):
         | 
| 28 | 
            +
                        angle = 0.01 + np.random.randint(config["ma"])
         | 
| 29 | 
            +
                        if i % 2 == 0:
         | 
| 30 | 
            +
                            angle = 2 * 3.1415926 - angle
         | 
| 31 | 
            +
                        length = 10 + np.random.randint(config["ml"])
         | 
| 32 | 
            +
                        brush_w = 5 + np.random.randint(config["mbw"])
         | 
| 33 | 
            +
                        end_x = (start_x + length * np.sin(angle)).astype(np.int32)
         | 
| 34 | 
            +
                        end_y = (start_y + length * np.cos(angle)).astype(np.int32)
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                        cv2.line(mask, (start_y, start_x), (end_y, end_x), 255.0, brush_w)
         | 
| 37 | 
            +
                        start_x, start_y = end_x, end_y
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                mask = mask.astype(np.uint8)
         | 
| 40 | 
            +
                cv2.imwrite(MASKIMAGE, mask)
         | 
| 41 | 
            +
             | 
| 42 | 
            +
             | 
| 43 | 
            +
            def create_bbox_mask():
         | 
| 44 | 
            +
                shape = list(RESIZE_TO)
         | 
| 45 | 
            +
                margin = [10, 10]
         | 
| 46 | 
            +
                bbox_shape = [30, 30]
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def random_bbox(shape, margin, bbox_shape):
         | 
| 49 | 
            +
                    """Generate a random tlhw with configuration.
         | 
| 50 | 
            +
                    Args:
         | 
| 51 | 
            +
                        config: Config should have configuration including IMG_SHAPES,
         | 
| 52 | 
            +
                                VERTICAL_MARGIN, HEIGHT, HORIZONTAL_MARGIN, WIDTH.
         | 
| 53 | 
            +
                    Returns:
         | 
| 54 | 
            +
                        tuple: (top, left, height, width)
         | 
| 55 | 
            +
                    """
         | 
| 56 | 
            +
                    img_height, img_width = shape
         | 
| 57 | 
            +
                    height, width = bbox_shape
         | 
| 58 | 
            +
                    ver_margin, hor_margin = margin
         | 
| 59 | 
            +
                    maxt = img_height - ver_margin - height
         | 
| 60 | 
            +
                    maxl = img_width - hor_margin - width
         | 
| 61 | 
            +
                    t = np.random.randint(low=ver_margin, high=maxt)
         | 
| 62 | 
            +
                    l = np.random.randint(low=hor_margin, high=maxl)
         | 
| 63 | 
            +
                    h = height
         | 
| 64 | 
            +
                    w = width
         | 
| 65 | 
            +
                    return (t, l, h, w)
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                bboxs = []
         | 
| 68 | 
            +
                for i in range(20):
         | 
| 69 | 
            +
                    bbox = random_bbox(shape, margin, bbox_shape)
         | 
| 70 | 
            +
                    bboxs.append(bbox)
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                height, width = shape
         | 
| 73 | 
            +
                mask = np.zeros((height, width), np.float32)
         | 
| 74 | 
            +
                # print(mask.shape)
         | 
| 75 | 
            +
                for bbox in bboxs:
         | 
| 76 | 
            +
                    h = int(bbox[2] * 0.1) + np.random.randint(int(bbox[2] * 0.2 + 1))
         | 
| 77 | 
            +
                    w = int(bbox[3] * 0.1) + np.random.randint(int(bbox[3] * 0.2) + 1)
         | 
| 78 | 
            +
                    mask[
         | 
| 79 | 
            +
                        (bbox[0] + h) : (bbox[0] + bbox[2] - h),
         | 
| 80 | 
            +
                        (bbox[1] + w) : (bbox[1] + bbox[3] - w),
         | 
| 81 | 
            +
                    ] = 255.0
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                mask = mask.astype(np.uint8)
         | 
| 84 | 
            +
                cv2.imwrite(MASKIMAGE, mask)
         | 
    	
        inpaint.py
    ADDED
    
    | @@ -0,0 +1,121 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import os
         | 
| 2 | 
            +
            import torch
         | 
| 3 | 
            +
            import torch.nn as nn
         | 
| 4 | 
            +
            from torch.utils.data import DataLoader
         | 
| 5 | 
            +
            from types import SimpleNamespace
         | 
| 6 | 
            +
            from deepfillv2 import test_dataset, utils
         | 
| 7 | 
            +
            from config import *
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            class InpaintingTester:
         | 
| 10 | 
            +
                def __init__(self, save_path, resize_to=None):
         | 
| 11 | 
            +
                    if resize_to is None:
         | 
| 12 | 
            +
                        resize_to = RESIZE_TO
         | 
| 13 | 
            +
                    self.save_path = save_path
         | 
| 14 | 
            +
                    self.setsize = resize_to
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    # Build the generator network
         | 
| 17 | 
            +
                    opt = SimpleNamespace(
         | 
| 18 | 
            +
                        pad_type=PAD_TYPE,
         | 
| 19 | 
            +
                        in_channels=IN_CHANNELS,
         | 
| 20 | 
            +
                        out_channels=OUT_CHANNELS,
         | 
| 21 | 
            +
                        latent_channels=LATENT_CHANNELS,
         | 
| 22 | 
            +
                        activation=ACTIVATION,
         | 
| 23 | 
            +
                        norm=NORM,
         | 
| 24 | 
            +
                        init_type=INIT_TYPE,
         | 
| 25 | 
            +
                        init_gain=INIT_GAIN,
         | 
| 26 | 
            +
                        use_cuda=CUDA,
         | 
| 27 | 
            +
                        gpu_device=GPU_DEVICE,
         | 
| 28 | 
            +
                    )
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    # Initialize generator (only once)
         | 
| 31 | 
            +
                    self.generator = utils.create_generator(opt).eval()
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    # Load pretrained model weights
         | 
| 34 | 
            +
                    # print("-- INPAINT: Loading Pretrained Model --")
         | 
| 35 | 
            +
                    self.load_model_generator(self.generator)
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                    # Move the generator to GPU
         | 
| 38 | 
            +
                    self.generator = self.generator.to(GPU_DEVICE)
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def load_model_generator(self, generator):
         | 
| 41 | 
            +
                    pretrained_dict = torch.load(
         | 
| 42 | 
            +
                        DEEPFILL_MODEL_PATH, map_location=torch.device(GPU_DEVICE), weights_only=True
         | 
| 43 | 
            +
                    )
         | 
| 44 | 
            +
                    generator.load_state_dict(pretrained_dict)
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                def process_image(self, in_image, mask_image, save_image_path):
         | 
| 47 | 
            +
                    # Initialize dataset and dataloader
         | 
| 48 | 
            +
                    trainset = test_dataset.InpaintDataset(in_image, mask_image, self.setsize)
         | 
| 49 | 
            +
                    dataloader = DataLoader(
         | 
| 50 | 
            +
                        trainset,
         | 
| 51 | 
            +
                        batch_size=1,
         | 
| 52 | 
            +
                        shuffle=False,
         | 
| 53 | 
            +
                        num_workers=8,
         | 
| 54 | 
            +
                        pin_memory=True,
         | 
| 55 | 
            +
                    )
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                    # Testing loop for a single image
         | 
| 58 | 
            +
                    for batch_idx, (img, mask) in enumerate(dataloader):
         | 
| 59 | 
            +
                        img = img.to(GPU_DEVICE)
         | 
| 60 | 
            +
                        mask = mask.to(GPU_DEVICE)
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                        # Generator output
         | 
| 63 | 
            +
                        with torch.no_grad():
         | 
| 64 | 
            +
                            first_out, second_out = self.generator(img, mask)
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                        # Combine outputs with input
         | 
| 67 | 
            +
                        first_out_wholeimg = img * (1 - mask) + first_out * mask
         | 
| 68 | 
            +
                        second_out_wholeimg = img * (1 - mask) + second_out * mask
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                        masked_img = img * (1 - mask) + mask
         | 
| 71 | 
            +
                        mask = torch.cat((mask, mask, mask), 1)
         | 
| 72 | 
            +
                        img_list = [second_out_wholeimg]
         | 
| 73 | 
            +
                        name_list = ["second_out"]
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                        # Save the sample image
         | 
| 76 | 
            +
                        results_path = os.path.dirname(save_image_path)
         | 
| 77 | 
            +
                        if not os.path.exists(results_path):
         | 
| 78 | 
            +
                            os.makedirs(results_path)
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                        utils.save_sample_png(
         | 
| 81 | 
            +
                            sample_folder=results_path,
         | 
| 82 | 
            +
                            sample_name=os.path.basename(save_image_path),
         | 
| 83 | 
            +
                            img_list=img_list,
         | 
| 84 | 
            +
                            name_list=name_list,
         | 
| 85 | 
            +
                            pixel_max_cnt=255,
         | 
| 86 | 
            +
                        )
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                def process_multiple_images(self, image_mask_pairs):
         | 
| 89 | 
            +
                    # Iterate through a list of image/mask pairs and save results
         | 
| 90 | 
            +
                    png_images=[]
         | 
| 91 | 
            +
                    for img_path, mask_path in image_mask_pairs:
         | 
| 92 | 
            +
                        try:
         | 
| 93 | 
            +
                            save_image_path = os.path.join(self.save_path, os.path.basename(img_path))
         | 
| 94 | 
            +
                            print(f"Processing: {img_path} and {mask_path}")
         | 
| 95 | 
            +
                            self.process_image(img_path, mask_path, save_image_path)
         | 
| 96 | 
            +
                            extention = os.path.splitext(save_image_path)[1]
         | 
| 97 | 
            +
                            save_at=save_image_path.replace(extention, ".png")
         | 
| 98 | 
            +
                            png_images.append(save_at)
         | 
| 99 | 
            +
                        except Exception as e:
         | 
| 100 | 
            +
                            if self.save_path in png_images:
         | 
| 101 | 
            +
                                png_images.pop()
         | 
| 102 | 
            +
                                png_images.append(None)
         | 
| 103 | 
            +
                            print(f"Error: {e}")
         | 
| 104 | 
            +
                    # print("-- All Inpainting is finished --")
         | 
| 105 | 
            +
                    return png_images
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            # Main execution
         | 
| 108 | 
            +
            # if __name__ == "__main__":
         | 
| 109 | 
            +
            #     save_path = "./output"
         | 
| 110 | 
            +
            #     resize_to = None  # Default size from config
         | 
| 111 | 
            +
             | 
| 112 | 
            +
            #     # List of image and mask pairs
         | 
| 113 | 
            +
            #     image_mask_pairs = [
         | 
| 114 | 
            +
            #         ( "./input/image.jpg", "./input/mask.jpg"),
         | 
| 115 | 
            +
            #     ]
         | 
| 116 | 
            +
             | 
| 117 | 
            +
            #     tester = InpaintingTester(save_path, resize_to)
         | 
| 118 | 
            +
                
         | 
| 119 | 
            +
            #     # Process multiple images using a loop
         | 
| 120 | 
            +
            #     results=tester.process_multiple_images(image_mask_pairs)
         | 
| 121 | 
            +
            #     print(results)
         | 
 
			
