PierreBrunelle commited on
Commit
152a369
1 Parent(s): dbb6379

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +117 -0
app.py ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pixeltable as pxt
3
+ from pixeltable.functions.huggingface import clip_image, clip_text
4
+ from pixeltable.iterators import FrameIterator
5
+ import PIL.Image
6
+ import os
7
+
8
+ # Embedding functions
9
+ @pxt.expr_udf
10
+ def embed_image(img: PIL.Image.Image):
11
+ return clip_image(img, model_id='openai/clip-vit-base-patch32')
12
+
13
+ @pxt.expr_udf
14
+ def str_embed(s: str):
15
+ return clip_text(s, model_id='openai/clip-vit-base-patch32')
16
+
17
+ # Process video and create index
18
+ def process_video(video_file, progress=gr.Progress()):
19
+
20
+ progress(0, desc="Initializing...")
21
+
22
+ # Pixeltable setup
23
+ pxt.drop_dir('video_search', force=True)
24
+ pxt.create_dir('video_search')
25
+
26
+ video_table = pxt.create_table('video_search.videos', {'video': pxt.VideoType()})
27
+
28
+ frames_view = pxt.create_view(
29
+ 'video_search.frames',
30
+ video_table,
31
+ iterator=FrameIterator.create(video=video_table.video, fps=1)
32
+ )
33
+
34
+ progress(0.2, desc="Inserting video...")
35
+ video_table.insert([{'video': video_file.name}])
36
+
37
+ progress(0.4, desc="Creating embedding index...")
38
+ frames_view.add_embedding_index('frame', string_embed=str_embed, image_embed=embed_image)
39
+
40
+ progress(1.0, desc="Processing complete")
41
+ return "Video processed and indexed successfully!"
42
+
43
+ # Perform similarity search
44
+ def similarity_search(query, search_type, num_results, progress=gr.Progress()):
45
+
46
+ frames_view = pxt.get_table('video_search.frames')
47
+
48
+ progress(0.5, desc="Performing search...")
49
+ if search_type == "Text":
50
+ sim = frames_view.frame.similarity(query)
51
+ else: # Image search
52
+ sim = frames_view.frame.similarity(query)
53
+
54
+ results = frames_view.order_by(sim, asc=False).limit(num_results).select(frames_view.frame, sim=sim).collect()
55
+
56
+ progress(1.0, desc="Search complete")
57
+
58
+ return [row['frame'] for row in results]
59
+
60
+ # Gradio interface
61
+ with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
62
+ gr.Markdown(
63
+ """
64
+ <div style=margin: 0 auto;">
65
+ <img src="https://raw.githubusercontent.com/pixeltable/pixeltable/main/docs/source/data/pixeltable-logo-large.png" alt="Pixeltable" style="max-width: 200px; margin-bottom: 20px;" />
66
+ <h1 style="margin-bottom: 0.5em;">Text and image similarity search on video frames with embedding indexes</h1>
67
+ </div>
68
+ """
69
+ )
70
+ gr.HTML(
71
+ """
72
+ <p>
73
+ <a href="https://github.com/pixeltable/pixeltable" target="_blank" style="color: #4D148C; text-decoration: none; font-weight: bold;">Pixeltable</a>
74
+ enables storage, versioning, indexing, and similarity search on video frames.
75
+ </p>
76
+ """
77
+ )
78
+
79
+ with gr.Tab("1. Upload and Process Video"):
80
+ video_file = gr.File(label="Upload Video")
81
+ process_button = gr.Button("Process Video")
82
+ process_output = gr.Textbox(label="Processing Status")
83
+
84
+ process_button.click(
85
+ process_video,
86
+ inputs=[video_file],
87
+ outputs=[process_output]
88
+ )
89
+
90
+ with gr.Tab("2. Text and Image Similarity Search on Frames"):
91
+ with gr.Row():
92
+ with gr.Column():
93
+ search_type = gr.Radio(["Text", "Image"], label="Search Type", value="Text")
94
+ text_input = gr.Textbox(label="Text Query")
95
+ image_input = gr.Image(label="Image Query", type="pil")
96
+ num_results = gr.Slider(minimum=1, maximum=20, value=5, step=1, label="Number of Results")
97
+ with gr.Column():
98
+ search_button = gr.Button("Search")
99
+ results_gallery = gr.Gallery(label="Search Results")
100
+
101
+ def update_search_input(choice):
102
+ return gr.update(visible=choice=="Text"), gr.update(visible=choice=="Image")
103
+
104
+ search_type.change(update_search_input, search_type, [text_input, image_input])
105
+
106
+ def perform_search(search_type, text_query, image_query, num_results):
107
+ query = text_query if search_type == "Text" else image_query
108
+ return similarity_search(query, search_type, num_results)
109
+
110
+ search_button.click(
111
+ perform_search,
112
+ inputs=[search_type, text_input, image_input, num_results],
113
+ outputs=[results_gallery]
114
+ )
115
+
116
+ if __name__ == "__main__":
117
+ demo.launch(debug=True)