random2222's picture
Update app.py
ea3cae7 verified
raw
history blame
13.8 kB
import cv2
import numpy as np
import os
import gradio as gr
from PIL import Image
import tempfile
# Enable OpenCL for better performance if available
try:
cv2.ocl.setUseOpenCL(True)
except:
pass # OpenCL might not be available in all environments
# ------------------- Black & White Converter Functions ------------------- #
def convert_to_black_white(image, threshold_value=127, method="otsu"):
"""Convert image to black and white using specified thresholding method"""
if isinstance(image, str):
image = cv2.imread(image)
# Convert to grayscale if not already
if len(image.shape) == 3:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
else:
gray = image
if method == "adaptive":
binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2)
elif method == "otsu":
_, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
else:
_, binary = cv2.threshold(gray, threshold_value, 255, cv2.THRESH_BINARY)
return binary
def process_image_bw(image, threshold_method, threshold_value):
"""Process image with black and white thresholding for Gradio"""
if image is None:
raise gr.Error("No image provided")
if threshold_method != "manual":
threshold_value = 0 # Not used for adaptive or Otsu
# Convert to numpy array if PIL Image
if isinstance(image, Image.Image):
image_np = np.array(image)
# Convert RGB to BGR for OpenCV
if len(image_np.shape) == 3:
image_np = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
else:
image_np = image
result = convert_to_black_white(image_np, threshold_value, threshold_method)
return Image.fromarray(result)
def process_video_bw(video_path, threshold_method, threshold_value):
"""Process video with black and white filter for Gradio"""
if video_path is None:
raise gr.Error("No video provided")
if threshold_method != "manual":
threshold_value = 0 # Not used for adaptive or Otsu
try:
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
raise gr.Error("Could not open video file")
# Get video properties
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = int(cap.get(cv2.CAP_PROP_FPS))
# Create temporary output file
temp_output = tempfile.NamedTemporaryFile(suffix='.mp4', delete=False)
output_path = temp_output.name
temp_output.close()
# Create video writer
out = cv2.VideoWriter(output_path, fourcc, fps, (frame_width, frame_height), isColor=False)
# Process each frame
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
bw_frame = convert_to_black_white(frame, threshold_value, threshold_method)
out.write(bw_frame)
cap.release()
out.release()
return output_path
except Exception as e:
raise gr.Error(f"Error processing video: {str(e)}")
# ------------------- Pencil Sketch Converter Functions ------------------- #
def process_image_sketch(image, intensity, blur_ksize, sigma):
"""Process image with pencil sketch effect for Gradio"""
if image is None:
raise gr.Error("No image provided")
# Convert to numpy array if PIL Image
if isinstance(image, Image.Image):
image_np = np.array(image)
# Convert RGB to BGR for OpenCV
if len(image_np.shape) == 3:
image_np = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
else:
image_np = image
# Convert to grayscale
gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY) if len(image_np.shape) == 3 else image_np
# Create sketch effect
inverted = cv2.bitwise_not(gray)
blur_ksize = blur_ksize if blur_ksize % 2 == 1 else blur_ksize + 1 # Ensure kernel size is odd
blurred = cv2.GaussianBlur(inverted, (blur_ksize, blur_ksize), sigma)
sketch = cv2.divide(gray, cv2.bitwise_not(blurred), scale=intensity)
return Image.fromarray(sketch)
def process_video_sketch(video_path, intensity, blur_ksize, sigma):
"""Process video with pencil sketch effect for Gradio"""
if video_path is None:
raise gr.Error("No video provided")
try:
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
raise gr.Error("Could not open video file")
# Get video properties
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = int(cap.get(cv2.CAP_PROP_FPS))
# Create temporary output file
temp_output = tempfile.NamedTemporaryFile(suffix='.mp4', delete=False)
output_path = temp_output.name
temp_output.close()
# Create video writer
out = cv2.VideoWriter(output_path, fourcc, fps, (frame_width, frame_height), isColor=True)
# Process each frame
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
inverted = cv2.bitwise_not(gray)
blur_ksize_adj = blur_ksize if blur_ksize % 2 == 1 else blur_ksize + 1
blurred = cv2.GaussianBlur(inverted, (blur_ksize_adj, blur_ksize_adj), sigma)
sketch = cv2.divide(gray, cv2.bitwise_not(blurred), scale=intensity)
sketch_bgr = cv2.cvtColor(sketch, cv2.COLOR_GRAY2BGR)
out.write(sketch_bgr)
cap.release()
out.release()
return output_path
except Exception as e:
raise gr.Error(f"Error processing video: {str(e)}")
# ------------------- Create Gradio Interface ------------------- #
def update_blur(value):
"""Ensure blur kernel size is always odd"""
return value if value % 2 == 1 else value + 1
def create_interface():
# App title and description
title = "Image & Video Processor"
description = """
# Image and Video Processing App
This app provides tools to convert images and videos to black & white or pencil sketch styles.
## Features:
- **Black & White Conversion**: Apply different thresholding methods
- **Pencil Sketch Effect**: Create artistic pencil drawings with customizable parameters
- **Support for both images and videos**
Made with ❤️ using Gradio and OpenCV
"""
# Black and White Image Interface
with gr.Blocks(title=title) as app:
gr.Markdown(description)
with gr.Tab("Black & White Converter"):
with gr.Tab("Image"):
with gr.Row():
with gr.Column():
bw_image_input = gr.Image(label="Input Image", type="numpy")
bw_method = gr.Radio(
choices=["otsu", "adaptive", "manual"],
value="otsu",
label="Thresholding Method"
)
bw_threshold = gr.Slider(
minimum=0,
maximum=255,
value=127,
step=1,
label="Manual Threshold (0-255)",
interactive=True
)
bw_image_btn = gr.Button("Convert to Black & White")
with gr.Column():
bw_image_output = gr.Image(label="Processed Image")
# Show/hide threshold slider based on method
def update_threshold_visibility(method):
return gr.update(visible=(method == "manual"))
bw_method.change(fn=update_threshold_visibility, inputs=bw_method, outputs=bw_threshold)
with gr.Tab("Video"):
with gr.Row():
with gr.Column():
bw_video_input = gr.Video(label="Input Video")
bw_video_method = gr.Radio(
choices=["otsu", "adaptive", "manual"],
value="otsu",
label="Thresholding Method"
)
bw_video_threshold = gr.Slider(
minimum=0,
maximum=255,
value=127,
step=1,
label="Manual Threshold (0-255)",
interactive=True
)
bw_video_btn = gr.Button("Convert to Black & White")
with gr.Column():
bw_video_output = gr.Video(label="Processed Video")
# Show/hide threshold slider based on method
bw_video_method.change(fn=update_threshold_visibility, inputs=bw_video_method, outputs=bw_video_threshold)
with gr.Tab("Pencil Sketch Converter"):
with gr.Tab("Image"):
with gr.Row():
with gr.Column():
sketch_image_input = gr.Image(label="Input Image", type="numpy")
sketch_intensity = gr.Slider(
minimum=1,
maximum=255,
value=255,
step=1,
label="Intensity (1-255)"
)
sketch_blur = gr.Slider(
minimum=1,
maximum=99,
value=21,
step=2,
label="Blur Kernel Size (odd, 1-99)"
)
sketch_sigma = gr.Slider(
minimum=0,
maximum=50,
value=0,
step=0.1,
label="Standard Deviation (0-50)"
)
sketch_image_btn = gr.Button("Convert to Pencil Sketch")
with gr.Column():
sketch_image_output = gr.Image(label="Processed Image")
with gr.Tab("Video"):
with gr.Row():
with gr.Column():
sketch_video_input = gr.Video(label="Input Video")
sketch_video_intensity = gr.Slider(
minimum=1,
maximum=255,
value=255,
step=1,
label="Intensity (1-255)"
)
sketch_video_blur = gr.Slider(
minimum=1,
maximum=99,
value=21,
step=2,
label="Blur Kernel Size (odd, 1-99)"
)
sketch_video_sigma = gr.Slider(
minimum=0,
maximum=50,
value=0,
step=0.1,
label="Standard Deviation (0-50)"
)
sketch_video_btn = gr.Button("Convert to Pencil Sketch")
with gr.Column():
sketch_video_output = gr.Video(label="Processed Video")
# Examples section
with gr.Accordion("Examples", open=False):
gr.Markdown("""
## Example Usage:
1. **Black & White Conversion**: Great for document scanning, text enhancement, or artistic effects
2. **Pencil Sketch**: Perfect for creating artistic renderings from photos
Try uploading your own images or videos!
""")
# Set up event listeners
bw_image_btn.click(
fn=process_image_bw,
inputs=[bw_image_input, bw_method, bw_threshold],
outputs=bw_image_output
)
bw_video_btn.click(
fn=process_video_bw,
inputs=[bw_video_input, bw_video_method, bw_video_threshold],
outputs=bw_video_output
)
sketch_image_btn.click(
fn=process_image_sketch,
inputs=[sketch_image_input, sketch_intensity, sketch_blur, sketch_sigma],
outputs=sketch_image_output
)
sketch_video_btn.click(
fn=process_video_sketch,
inputs=[sketch_video_input, sketch_video_intensity, sketch_video_blur, sketch_video_sigma],
outputs=sketch_video_output
)
# Make blur slider always odd
sketch_blur.change(update_blur, sketch_blur, sketch_blur)
sketch_video_blur.change(update_blur, sketch_video_blur, sketch_video_blur)
return app
# Create and launch the app
app = create_interface()
# This is needed for Hugging Face Spaces
if __name__ == "__main__":
app.launch()