qqwjq1981's picture
Upload 4 files
7c2b60c verified
raw
history blame
4.69 kB
import gradio as gr
import os
import tempfile
import numpy as np
import cv2
import img2pdf
from pathlib import Path
from pdf2image import convert_from_path # Make sure pdf2image is installed: pip install pdf2image opencv-python numpy img2pdf
# Define a default bounding box (e.g., for a logo area)
# Bounding box: (x1, y1, x2, y2) in fractions of image size
default_bbox = (0.75, 0.9, 0.98, 0.98)
def expand_bbox(bbox, expand_factor=0.3):
"""Expands a bounding box by a given factor."""
x_min, y_min, x_max, y_max = bbox
width = x_max - x_min
height = y_max - y_min
new_x_min = max(0, x_min - width * expand_factor)
new_y_min = max(0, y_min - height * expand_factor)
new_x_max = min(1, x_max + width * expand_factor)
new_y_max = min(1, y_max + height * expand_factor)
return (new_x_min, new_y_min, new_x_max, new_y_max)
def inpaint_image(image_np, bbox, color=(255, 255, 255)):
"""
Inpaints a specified bounding box area in an image with a solid color.
image_np: NumPy array of the image (BGR format).
bbox: Tuple (x_min, y_min, x_max, y_max) in relative coordinates (0 to 1).
color: Tuple (B, G, R) for the inpaint color.
"""
h, w, _ = image_np.shape
x1 = int(bbox[0] * w)
y1 = int(bbox[1] * h)
x2 = int(bbox[2] * w)
y2 = int(bbox[3] * h)
# Create a copy to avoid modifying the original image array directly
inpainted_image = image_np.copy()
# Fill the bounding box with the specified color
cv2.rectangle(inpainted_image, (x1, y1), (x2, y2), color, -1) # -1 fills the rectangle
return inpainted_image
# --- End Placeholder functions ---
def process_pdf(pdf_file):
"""
Processes a PDF file, inpainting specified areas on each page.
"""
try:
# Use test.pdf if nothing uploaded
# Ensure 'wifi_basics_teaching_genspark.pdf' exists in the same directory
# as your script for this to work when no file is uploaded.
pdf_path = pdf_file.name if pdf_file else "wifi_basics_teaching_genspark.pdf"
assert os.path.exists(pdf_path), f"File not found: {pdf_path}. Please upload a PDF or ensure 'wifi_basics_teaching_genspark.pdf' is in the current directory."
# Define inpaint colors per page
page_inpaint_colors = {
0: (255, 255, 255), # white for page 0 (BGR)
1: (0, 0, 0) # black for page 1 (BGR)
}
with tempfile.TemporaryDirectory() as tmpdir:
# Convert PDF pages to images
images = convert_from_path(pdf_path, dpi=300, output_folder=tmpdir, fmt="png")
output_images = []
for i, img in enumerate(images):
# Convert PIL RGB to OpenCV BGR
np_img = np.array(img)[:, :, ::-1]
# Expand the default bounding box for inpainting
bbox = expand_bbox(default_bbox, expand_factor=0.3)
# Get color for the current page, default to white if not specified
color = page_inpaint_colors.get(i, (255, 255, 255))
# Perform inpainting
inpainted = inpaint_image(np_img, bbox, color=color)
# Save the inpainted image
img_path = os.path.join(tmpdir, f"page_{i}.png")
cv2.imwrite(img_path, inpainted)
output_images.append(img_path)
# Convert inpainted images back to a single PDF
output_pdf = os.path.join(tmpdir, "inpainted_output.pdf")
# Sort images by path to ensure correct page order in the output PDF
with open(output_pdf, "wb") as f:
f.write(img2pdf.convert([Path(p) for p in sorted(output_images)]))
return output_pdf
except Exception as e:
print(f"❌ Error during PDF processing: {e}")
# Return None to indicate an error, which safe_process_wrapper will handle
return None
# Gradio app UI
with gr.Blocks() as demo:
gr.Markdown("### 🧽 PDF Logo Inpainting (Solid Fill, Expand + Color Config)")
with gr.Row():
# Input component for PDF upload
pdf_input = gr.File(
label="Upload PDF (or leave empty to use test.pdf)",
file_types=[".pdf"],
interactive=True
)
# Output component for the processed PDF
pdf_output = gr.File(label="Download Inpainted PDF")
# Button to trigger the processing
run_button = gr.Button("Process and Inpaint")
# Link the button click to the processing function
run_button.click(
fn=process_pdf,
inputs=pdf_input,
outputs=pdf_output
)
# Launch the Gradio application
demo.launch()