File size: 7,648 Bytes
0d3c634
1f0ca43
 
 
0d3c634
0b72e1a
297cb09
1f0ca43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297cb09
2f2ea20
 
b4adb3f
 
fdcad1d
b4adb3f
 
 
 
2f2ea20
1f0ca43
2f2ea20
 
b4de5ec
 
2f2ea20
2345fb7
2f2ea20
6c8d288
2345fb7
 
 
 
 
 
6c8d288
 
b4adb3f
2f2ea20
 
1f0ca43
0b72e1a
1f0ca43
 
 
d91db0a
b4de5ec
 
1f0ca43
 
0d3c634
17df7d6
1f0ca43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#from transformers import load_tool, ReactCodeAgent, HfApiEngine
from PIL import Image, ImageDraw, ImageFont
import tempfile
import gradio as gr
from smolagents import CodeAgent, InferenceClientModel
from smolagents import HfApiModel,  DuckDuckGoSearchTool
#from transformers import load_tool

#%% Methods
# Function to add a label to an image
def add_label_to_image(image, label):
    # Create a drawing context
    draw = ImageDraw.Draw(image)
    
    # Define font size and color (adjust font path for your environment)
    font_path = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"  # Example font path
    font_size = 30  # Larger font size for better visibility
    try:
        font = ImageFont.truetype(font_path, font_size)
    except:
        font = ImageFont.load_default()
    
    # Calculate the size and position of the text (aligned to the left)
    text_bbox = draw.textbbox((0, 0), label, font=font)
    text_width, text_height = text_bbox[2] - text_bbox[0], text_bbox[3] - text_bbox[1]
    position = (image.width - text_width - 20, image.height - text_height - 20)# right-aligned with margin
    
    # Add a semi-transparent rectangle behind the text for better visibility
    rect_margin = 10
    rect_position = [
        position[0] - rect_margin,
        position[1] - rect_margin,
        position[0] + text_width + rect_margin,
        position[1] + text_height + rect_margin,
    ]
    draw.rectangle(rect_position, fill=(0, 0, 0, 128))  # Semi-transparent black
    draw.text(position, label, fill="white", font=font)
    return image


# Function to plot, label, and save an image
def plot_and_save_agent_image(agent_image, label, save_path=None):
    # Convert AgentImage to a raw PIL Image
    pil_image = agent_image.to_raw()

    # Add a label to the image
    labeled_image = add_label_to_image(pil_image, label)

    # Plot the image using PIL's show method
    labeled_image.show()

    # If save_path is provided, save the image
    if save_path:
        labeled_image.save(save_path)
        print(f"Image saved to {save_path}")
    else:
        print("No save path provided. Image not saved.")

# Function to generate prompts for an object
def generate_prompts_for_object(object_name):
    prompts = {
        "past": f"Show an old version of a {object_name} from its early days.",
        "present": f"Show a {object_name} with current features/design/technology.",
        "future": f"Show a futuristic version of a {object_name}, by predicting advanced features and futuristic design."
    }
    return prompts

# Function to generate the object's history images and GIF
def generate_object_history(object_name):
    images = []
    
    # Get prompts for the object
    prompts = generate_prompts_for_object(object_name)
    labels = {
        "past": f"{object_name} - Past",
        "present": f"{object_name} - Present",
        "future": f"{object_name} - Future"
    }
    
    # Generate sequential images and display them
    for time_period, frame in prompts.items():
        print(f"Generating {time_period} frame: {frame}")
        result = agent.run(frame)  # The tool generates the image
        
        # Append the image to the list for GIF creation
        images.append(result.to_raw())  # Ensure we're using raw image for GIF

        # Save each image with the appropriate name and label
        image_filename = f"{object_name}_{time_period}.png"
        plot_and_save_agent_image(result, labels[time_period], save_path=image_filename)
        
    # Create GIF from images
    gif_path = f"{object_name}_evolution.gif"
    images[0].save(
        gif_path, 
        save_all=True, 
        append_images=images[1:], 
        duration=1000,  # Duration in milliseconds for each frame
        loop=0          # Infinite loop
    )
    
    # Return images and GIF path
    return images, gif_path

#%% Initialization of tools and AI_Agent
# Import text-to-image tool from Hub
from smolagents.tools import Tool, load_tool

'''
image_generation_tool = Tool.from_space(
    space_id="m-ric/text-to-image",
    name="image_generator",
    description="Generate an image from a prompt"
)
'''

from smolagents import load_tool

image_generation_tool = load_tool(
    repo_id="m-ric/text-to-image",  # The Hugging Face Space repo
    trust_remote_code=True,         
    cache=False                     
)

'''
class WrappedTextToImageTool(Tool):
    name = "text_to_image"
    description = "Generates an image from a text prompt using the m-ric/text-to-image tool."
    inputs = ["prompt"]  # Optional: only if smolagents uses this

    def run(self, prompt: str) -> str:
        return image_generation_tool(prompt)

image_generation_tool = WrappedTextToImageTool()
'''


# Import search tool from LangChain
#from transformers.agents.search import DuckDuckGoSearchTool
search_tool = DuckDuckGoSearchTool()

# Load the LLM engine
#llm_engine = HfApiEngine("Qwen/Qwen2.5-72B-Instruct")
#llm_engine =HfApiModel("Qwen/Qwen2.5-72B-Instruct")
llm_engine= InferenceClientModel("Qwen/Qwen2.5-72B-Instruct")

# Initialize the agent with both tools
#agent = ReactCodeAgent(tools=[image_generation_tool, search_tool], llm_engine=llm_engine)
agent = CodeAgent(tools=[image_generation_tool, search_tool], model=llm_engine)

# Gradio interface
def create_gradio_interface():
    with gr.Blocks() as demo:
        gr.Markdown("# TimeMetamorphy: an object Evolution Generator")
        
        # Add a section for instructions
        gr.Markdown("""
        ## Unlocking the secrets of time!
        This app unveils these mysteries by offering a unique/magic lens that allows us "time travel". 
        Powered by AI agents equipped with cutting-edge tools, it provides the superpower to explore the past, witness the present, and dream up the future like never before.
        
        This system allows you to generate visualizations of how an object/concept, like a bicycle or a car, may have evolved over time. 
        It generates images of the object in the past, present, and future based on your input.
        
        ### Default Example: Evolution of a Car
        Below, you can see a precomputed example of a "car" evolution. Enter another object to generate its evolution.
        """)

        # Paths to the precomputed files
        default_images = [
            ("car_past.png", "Car - Past"),
            ("car_present.png", "Car - Present"),
            ("car_future.png", "Car - Future")
        ]
        default_gif_path = "car_evolution.gif"

        with gr.Row():
            with gr.Column():
                # Textbox for user to input an object name
                object_name_input = gr.Textbox(label="Enter an object name (e.g., bicycle, phone)", 
                                              placeholder="Enter an object name", 
                                              lines=1)

                # Button to trigger the generation of images and GIF
                generate_button = gr.Button("Generate Evolution")
    
                # Gradio Gallery component to display the images
                image_gallery = gr.Gallery(label="Generated Images", show_label=True, columns=3, rows=1, value=default_images)

                # Output for the generated GIF
                gif_output = gr.Image(label="Generated GIF", show_label=True, value=default_gif_path)
         
        # Set the action when the button is clicked
        generate_button.click(fn=generate_object_history, inputs=[object_name_input], outputs=[image_gallery, gif_output])
    
    return demo

# Launch the Gradio app 
demo = create_gradio_interface()
demo.launch(share=True)