Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added src/__pycache__/async_request.cpython-312.pyc
Binary file not shown.
Binary file added src/__pycache__/main.cpython-312.pyc
Binary file not shown.
Binary file modified src/__pycache__/scene_split.cpython-312.pyc
Binary file not shown.
Binary file modified src/__pycache__/slideshow.cpython-312.pyc
Binary file not shown.
Binary file modified src/__pycache__/text_to_img.cpython-312.pyc
Binary file not shown.
27 changes: 23 additions & 4 deletions src/async_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,37 @@
from typing import Dict, Any

async def send_request(session: aiohttp.ClientSession, url: str, data: Dict[str, Any]) -> None:
"""
Sends an asynchronous POST request to the specified URL with the given data.

Args:
session (aiohttp.ClientSession): The aiohttp session to use for the request.
url (str): The URL to send the request to.
data (Dict[str, Any]): The JSON data to include in the request body.
"""
async with session.post(url, json=data) as response:
print(f"Sent request to {url}")

async def periodic_requests(url: str, data: Dict[str, Any], interval: int, count: int) -> None:
"""
Sends periodic asynchronous requests to a specified URL.

Args:
url (str): The URL to send requests to.
data (Dict[str, Any]): The data to send with each request.
interval (int): The time interval (in seconds) between requests.
count (int): The total number of requests to send.
"""
async with aiohttp.ClientSession() as session:
for _ in range(count):
asyncio.create_task(send_request(session, url, data)) # Fire and forget
await asyncio.sleep(interval) # Wait before sending the next request
# Schedule the request to be sent immediately (fire and forget)
asyncio.create_task(send_request(session, url, data))
# Pause execution for the specified interval without blocking the event loop
await asyncio.sleep(interval)

url = "https://api.example.com/endpoint"
data = {"key": "value"}
interval = 5 # Seconds between requests
count = 10 # Number of requests
interval = 5
count = 10

asyncio.run(periodic_requests(url, data, interval, count))
29 changes: 22 additions & 7 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -1,46 +1,61 @@
import timeit
# Start the timer to measure the total execution time of the script
start = timeit.default_timer()
import json
import os
import scene_split
import text_to_img
import shutil

# Read the story content from a text file
with open("story.txt", "r", encoding="utf-8") as f:
story = f.read()

def clear_story_folder(folder_path: str = "story") -> None:
"""
Clears the specified folder if it exists, or creates it if it doesn't.

Args:
folder_path (str): The path to the folder. Defaults to "story".
"""
# Check if the folder already exists
if os.path.exists(folder_path):
# Remove the folder and all its contents
shutil.rmtree(folder_path)
# Create a new, empty folder
os.makedirs(folder_path)

# Prepare the output directory for images
clear_story_folder()

# Split the story into distinct scenes using semantic similarity
# The threshold 0.7 determines how similar sentences must be to remain in the same scene
scenes = scene_split.main(story,0.7)
print("Scenes splitted successfully!")
# print(scenes)
# for i in scenes:
# print(i[0])

# Scenes to prompt
# print(scenes)
number_of_scenes = len(scenes)
print(f"Number of scenes: {number_of_scenes}")

print("\n")
# Prompt the user for the desired artistic style
image_type = input("Enter the type of image you want to generate (realistic, cartoon, abstract): ")
print("\n")

# Iterate through each scene to generate a corresponding image
for i, scene in enumerate(scenes, 1):
# Construct the prompt for image generation, including the user's chosen style
prompt = f"Make a {image_type} image of" + scene
# print(prompt)
# Call the image generation function
text_to_img.main(prompt, f"story/image-{i}")

# Folder and File name generation
# Create a dictionary mapping image filenames to their corresponding scene text
story_dict = {f"story/image-{i}.png": line for i, line in enumerate(scenes, 1)}

# Save the mapping to a JSON file for use in the slideshow
with open("story.json", "w") as f:
json.dump(story_dict, f, indent=4)

# Stop the timer and print the total execution time
end = timeit.default_timer()
print(f"Time taken: {end-start} seconds")

Expand Down
34 changes: 33 additions & 1 deletion src/scene_split.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,28 @@
story_text: str = """John walked into the forest. He heard rustling behind him. The trees loomed tall as he pressed forward, his heart pounding. Later that night, he found a small cabin. It looked abandoned, but the door creaked open when he pushed it. The wind howled outside as he stepped in. Inside the cabin, an old man sat by the fire. He wore a long cloak and stared at John as if expecting him. In the morning, John woke up to find the man missing. The fire had gone cold. He stepped outside and saw footprints leading into the misty woods. With no other choice, he followed the footprints. The deeper he went, the more uneasy he felt, as if someone—or something—was watching him."""

def split_into_sentences(text: str) -> List[str]:
"""
Splits a given text into a list of sentences based on punctuation.

Args:
text (str): The input text to split.

Returns:
List[str]: A list of sentences found in the text.
"""
return re.findall(r"[^.!?]+", text)

def main(story_text: str, threshold: float = 0.5) -> List[str]:
"""
Splits the story text into meaningful scenes using semantic similarity.

Args:
story_text (str): The full text of the story.
threshold (float): The similarity threshold for merging sentences. Defaults to 0.5.

Returns:
List[str]: A list of merged sentences representing scenes.
"""
index_name = "text-search"
sentences = split_into_sentences(story_text)

Expand All @@ -24,26 +43,39 @@ def main(story_text: str, threshold: float = 0.5) -> List[str]:
pc = Pinecone(api_key=api_key)
index = pc.Index(index_name)

# Load the SentenceTransformer model for generating text embeddings
model = SentenceTransformer("all-MiniLM-L6-v2")
# Generate embeddings for all sentences at once
embeddings = model.encode(sentences)

merged_sentences = []
similarity_array = []
i = 0
# Iterate through sentences to determine if they should be merged
while i < len(sentences) - 1:
# Get embeddings for current and next sentence
vector_1, vector_2 = embeddings[i], embeddings[i + 1]

# Example of querying Pinecone index (if used in future)
response = index.query(vector=vector_1.tolist(), top_k=1, include_values=True)

# Calculate Cosine Similarity between the two sentence vectors
# Formula: (A . B) / (||A|| * ||B||)
similarity = np.dot(vector_1, vector_2) / (np.linalg.norm(vector_1) * np.linalg.norm(vector_2))

similarity_array.append([similarity,sentences[i],sentences[i+1]])

# If sentences are similar enough, merge them into one scene
if similarity >= threshold:
sentences[i + 1] = sentences[i] + ". " + sentences[i + 1]
else:
# Otherwise, the current sentence is a complete scene
merged_sentences.append(sentences[i])

i += 1

# Append the last sentence/scene
merged_sentences.append(sentences[-1])
# print("Similarity array:", similarity_array)
return merged_sentences

if __name__ == "__main__":
Expand Down
31 changes: 29 additions & 2 deletions src/slideshow.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,56 +6,83 @@
with open("story.json", 'r') as file:
image_texts = json.load(file)

# Iterate through keys to get image paths
image_paths: List[str] = list(image_texts.keys())
# print(image_texts)

# Initialize the main window for the application
root = tk.Tk()
root.title("Image Slideshow with Text")

# Label widget to display the image
img_label = tk.Label(root)
img_label.pack()

# Label widget to display the text, with wrapping
text_label = tk.Label(root, text="", font=("Arial", 14), wraplength=600)
text_label.pack(pady=10)

idx: int = 0
paused: bool = False

def update_image() -> None:
"""
Updates the displayed image and text based on the current index.
Schedules the next update unless paused.
"""
global idx, paused
# If paused, do not update the image
if paused:
return

# Retrieve current image path and text
img_path = image_paths[idx]
text = image_texts[img_path]

# Open and resize the image for display
img = Image.open(img_path)
img = img.resize((600, 400))
img = ImageTk.PhotoImage(img)

# Update the labels
img_label.config(image=img)
img_label.image = img
img_label.image = img # Keep a reference to prevent garbage collection
text_label.config(text=text)

# Move to the next index (looping back to 0 if at end)
idx = (idx + 1) % len(image_texts)

# Schedule this function to run again after 5000ms (5 seconds)
root.after(5000, update_image)

def toggle_pause() -> None:
"""
Toggles the pause state of the slideshow.
"""
global paused
paused = not paused
# If unpausing, immediately update to resume the cycle
if not paused:
update_image()

def next_image() -> None:
"""
advances to the next image in the slideshow.
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring should start with a capital letter. "advances" should be "Advances".

Suggested change
advances to the next image in the slideshow.
Advances to the next image in the slideshow.

Copilot uses AI. Check for mistakes.
"""
global idx
# Increment index with wrap-around
idx = (idx + 1) % len(image_texts)
update_image()

def prev_image() -> None:
"""
Moves to the previous image in the slideshow.
"""
global idx
# Decrement index with wrap-around
idx = (idx - 1) % len(image_texts)
update_image()

# Frame to hold control buttons
btn_frame = tk.Frame(root)
btn_frame.pack()

Expand Down
19 changes: 15 additions & 4 deletions src/text_to_img.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,34 @@
client = Together(api_key=TOGETHER_API_KEY)

def main(myprompt: str, img_file_name: str):
"""
Generates an image from a prompt using the Together AI API and saves it to a file.

Args:
myprompt (str): The text prompt for scanning content.
img_file_name (str): The base name for the output image file (without extension).
"""
# Call the Together AI API to generate an image
response = client.images.generate(
prompt=myprompt,
model="black-forest-labs/FLUX.1-schnell-Free",
width=1024,
height=768,
steps=1,
n=1,
response_format="b64_json",
response_format="b64_json", # Request the image as a Base64 encoded string
)
# print(response.data[0].b64_json)

# Extract the Base64 string from the response
imgstring: str = response.data[0].b64_json

# Decode the Base64 string into binary image data
imgdata: bytes = base64.b64decode(imgstring)

# Construct the filename and save the binary data
filename: str = f'{img_file_name}.png'
with open(filename, 'wb') as f:
f.write(imgdata)
# image = Image.open(filename)
# image.show()

if __name__=="__main__":
main("Cat eating burger", "burger-cat")