| import gradio as gr | |
| import numpy as np | |
| import cv2 | |
| import torch | |
| import random | |
| import os | |
| import spaces | |
| ''' | |
| class ImageMorpher: | |
| def __init__(self, num_frames=30, fps=10): | |
| self.num_frames = num_frames | |
| self.fps = fps | |
| def morph_images(self, image_A, image_B): | |
| """Morphs two images.""" | |
| image_A = np.array(image_A) | |
| image_B = np.array(image_B) | |
| if image_A.shape != image_B.shape: | |
| raise ValueError("Images must have the same dimensions.") | |
| if image_A.dtype != image_B.dtype: | |
| raise ValueError("Images must have the same data type.") | |
| height, width, _ = image_A.shape | |
| morphed_images = [] | |
| for i in range(self.num_frames + 1): | |
| alpha = i / self.num_frames | |
| beta = 1 - alpha | |
| morphed_image = cv2.addWeighted(image_A, alpha, image_B, beta, 0) | |
| morphed_images.append(morphed_image) | |
| return morphed_images | |
| def create_mp4(self, images, output_path="output.mp4"): | |
| """Creates an MP4 video from a list of images.""" | |
| height, width, _ = images[0].shape | |
| fourcc = cv2.VideoWriter_fourcc(*'mp4v') | |
| video_writer = cv2.VideoWriter(output_path, fourcc, self.fps, (width, height)) | |
| for image in images: | |
| video_writer.write(image) | |
| video_writer.release() | |
| def morph_image_chain(self, images): | |
| """Morphs a chain of images and returns the video path.""" | |
| morphed_images = [] | |
| for i in range(len(images) - 1): | |
| morphed_images.extend(self.morph_images(images[i], images[i + 1])) | |
| self.create_mp4(morphed_images) | |
| return "output.mp4" | |
| def swap_to_gallery(images): | |
| return gr.update(value=images, visible=True), gr.update(visible=True), gr.update(visible=False) | |
| def upload_example_to_gallery(images, prompt, style, negative_prompt): | |
| return gr.update(value=images, visible=True), gr.update(visible=True), gr.update(visible=False) | |
| def remove_back_to_files(): | |
| return gr.update(visible=False), gr.update(visible=False), gr.update(visible=True) | |
| # Create an instance of the ImageMorpher class | |
| morpher = ImageMorpher() | |
| """ | |
| # Define the Gradio interface | |
| ### Description and style | |
| logo = r""" | |
| <center><img src='https://photo-maker.github.io/assets/logo.png' alt='PhotoMaker logo' style="width:80px; margin-bottom:10px"></center> | |
| """ | |
| title = r""" | |
| <h1 align="center">🤗 Morphy the morpher 🤗</h1> | |
| """ | |
| description = r""" | |
| <b></b> | |
| <br> | |
| Morph image chain into mp4 | |
| <br> | |
| How to use:<br> | |
| -Select two or more images using the "select" tool in the "Images" input field.<br> | |
| -Click "Submit".<br> | |
| The "Output Video" block will display the morphed video, which you can watch and download.<br> | |
| """ | |
| css = ''' | |
| .gradio-container {width: 85% !important} | |
| ''' | |
| """ | |
| with gr.Blocks(css=css) as demo: | |
| gr.Markdown(logo) | |
| gr.Markdown(title) | |
| gr.Markdown(description) | |
| with gr.Row(): | |
| with gr.Column(): | |
| fn=morpher.morph_image_chain, | |
| files = gr.File( | |
| label="Drag (Select) 1 or more photos of your face", | |
| file_types=["image"], | |
| file_count="multiple" | |
| ) | |
| inputs = gr.Gallery(label="Your images",type="numpy", visible=False, columns=5, rows=1, height=200) | |
| with gr.Column(visible=False) as clear_button: | |
| remove_and_reupload = gr.ClearButton(value="Remove and upload new ones", components=files, size="sm") | |
| with gr.Column(): | |
| outputs=gr.Video(label="Output Video",interactive=False), | |
| title="Image Chain Morphing App", | |
| with gr.Column(): | |
| gallery = gr.Gallery(label="Generated Images") | |
| files.upload(fn=swap_to_gallery, inputs=files, outputs=[files, clear_button, files]) | |
| remove_and_reupload.click(fn=remove_back_to_files, outputs=[files, clear_button, files]) | |
| demo.launch() | |
| """ | |
| import app1 | |
| ''' | |
| Explanation: | |
| ImageMorpher class: | |
| Encapsulates the morphing logic and video creation. | |
| Has num_frames and fps attributes for customization. | |
| morph_images method handles morphing two images. | |
| create_mp4 method creates the MP4 video. | |
| morph_image_chain method: | |
| Iterates through the input image list and morphs each pair. | |
| Creates the final MP4 video using create_mp4. | |
| Returns the path to the video file. | |
| ''' |