Spaces:
Running
Running
import gradio as gr | |
import numpy as np | |
import cv2 | |
def create_dot_effect(image, dot_size=10, spacing=2, invert=False): | |
# Convert to grayscale if image is color | |
if len(image.shape) == 3: | |
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) | |
else: | |
gray = image | |
# Apply adaptive thresholding to improve contrast | |
gray = cv2.adaptiveThreshold( | |
gray, | |
255, | |
cv2.ADAPTIVE_THRESH_GAUSSIAN_C, | |
cv2.THRESH_BINARY, | |
25, # Block size | |
5 # Constant subtracted from mean | |
) | |
# Create a blank canvas with white background if inverted | |
height, width = gray.shape | |
canvas = np.zeros_like(gray) if not invert else np.full_like(gray, 255) | |
# Calculate number of dots based on spacing | |
y_dots = range(0, height, dot_size + spacing) | |
x_dots = range(0, width, dot_size + spacing) | |
# Create dots based on brightness | |
dot_color = 255 if not invert else 0 | |
for y in y_dots: | |
for x in x_dots: | |
# Get the average brightness of the region | |
region = gray[y:min(y+dot_size, height), x:min(x+dot_size, width)] | |
if region.size > 0: | |
brightness = np.mean(region) | |
# Dynamic dot sizing based on brightness | |
relative_brightness = brightness / 255.0 | |
if invert: | |
relative_brightness = 1 - relative_brightness | |
# Draw circle with size proportional to brightness | |
radius = int((dot_size/2) * relative_brightness) | |
if radius > 0: | |
cv2.circle(canvas, | |
(x + dot_size//2, y + dot_size//2), | |
radius, | |
(dot_color), | |
-1) | |
return canvas | |
def process_video(video_path, dot_size=10, spacing=2, invert=False): | |
# Read the video | |
cap = cv2.VideoCapture(video_path) | |
if not cap.isOpened(): | |
return None | |
# Get video properties | |
fps = int(cap.get(cv2.CAP_PROP_FPS)) | |
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) | |
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) | |
# Calculate target dimensions (max 720p for performance) | |
max_height = 720 | |
if frame_height > max_height: | |
scale = max_height / frame_height | |
frame_width = int(frame_width * scale) | |
frame_height = max_height | |
# Create temporary output file | |
output_path = "temp_output.mp4" | |
fourcc = cv2.VideoWriter_fourcc(*'avc1') | |
out = cv2.VideoWriter(output_path, fourcc, fps, (frame_width, frame_height), False) | |
try: | |
while cap.isOpened(): | |
ret, frame = cap.read() | |
if not ret: | |
break | |
# Resize frame if needed | |
if frame.shape[0] > max_height: | |
frame = cv2.resize(frame, (frame_width, frame_height)) | |
# Convert BGR to RGB for processing | |
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) | |
# Apply dot effect | |
dotted_frame = create_dot_effect(frame_rgb, dot_size, spacing, invert) | |
# Write the frame | |
out.write(dotted_frame) | |
finally: | |
# Ensure resources are released | |
cap.release() | |
out.release() | |
return output_path | |
# Create Gradio interface | |
with gr.Blocks(title="ChatGPT Ad Maker") as iface: | |
gr.Markdown("# ChatGPT Ad Maker") | |
gr.Markdown("Convert your image or video into a dotted pattern. Adjust dot size and spacing using the sliders.") | |
with gr.Tab("Image"): | |
image_input = gr.Image(label="Input Image") | |
with gr.Row(): | |
img_dot_size = gr.Slider(minimum=2, maximum=20, value=10, step=1, label="Dot Size") | |
img_spacing = gr.Slider(minimum=0, maximum=10, value=2, step=1, label="Dot Spacing") | |
image_output = gr.Image(label="Dotted Output") | |
image_button = gr.Button("Process Image") | |
image_button.click( | |
fn=create_dot_effect, | |
inputs=[image_input, img_dot_size, img_spacing], | |
outputs=image_output | |
) | |
with gr.Tab("Video"): | |
video_input = gr.Video(label="Input Video") | |
with gr.Row(): | |
vid_dot_size = gr.Slider(minimum=2, maximum=20, value=10, step=1, label="Dot Size") | |
vid_spacing = gr.Slider(minimum=0, maximum=10, value=2, step=1, label="Dot Spacing") | |
vid_invert = gr.Checkbox(label="Invert", value=False) | |
video_output = gr.Video(label="Dotted Output", format="mp4") | |
video_button = gr.Button("Process Video") | |
video_button.click( | |
fn=process_video, | |
inputs=[video_input, vid_dot_size, vid_spacing, vid_invert], | |
outputs=video_output | |
) | |
if __name__ == "__main__": | |
iface.launch() | |