dodijk iskaj Prajakta Shouche commited on
Commit
7f2c8f8
1 Parent(s): f849799

API for a plot for video matching.

Browse files

Co-authored-by: iskaj <[email protected]>
Co-authored-by: Prajakta Shouche <[email protected]>

Files changed (2) hide show
  1. Matching Exploration.ipynb +124 -0
  2. app.py +38 -17
Matching Exploration.ipynb ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "metadata": {},
7
+ "outputs": [
8
+ {
9
+ "name": "stdout",
10
+ "output_type": "stream",
11
+ "text": [
12
+ "Using cache from '/Users/dodijk/Library/CloudStorage/OneDrive-RTLNederlandB.V/code/videomatch/gradio_cached_examples/13' directory. If method or examples have changed since last caching, delete this folder to clear cache.\n"
13
+ ]
14
+ }
15
+ ],
16
+ "source": [
17
+ "from app import *"
18
+ ]
19
+ },
20
+ {
21
+ "cell_type": "code",
22
+ "execution_count": 79,
23
+ "metadata": {},
24
+ "outputs": [],
25
+ "source": [
26
+ "video_index = index_hashes_for_video(video_urls[0])\n",
27
+ "target_indices = [index_hashes_for_video(x) for x in video_urls[-1:]]\n",
28
+ " \n",
29
+ "video_index.make_direct_map()\n",
30
+ "hash_vectors = np.array([video_index.reconstruct(i) for i in range(video_index.ntotal)])"
31
+ ]
32
+ },
33
+ {
34
+ "cell_type": "code",
35
+ "execution_count": 114,
36
+ "metadata": {},
37
+ "outputs": [
38
+ {
39
+ "data": {
40
+ "image/png": "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pZU4X1yFnRmF1jKVXApPF8UVziJqe9e0Muvy5csRFxcHjUYDjUaDXr164csvv3R0bERERC1mrLXgqRUHkfTGr5j66T4U6gyIDXRH/whPrPpbEjRKJmfUvtjdc/bOO+/gpZdewmOPPYbBgwcDAHbu3IlHHnkERUVFmD17tsODJCIiuhaZJVW479M9yCqpvlgoBVY8NAgeLsqmTyRyomsaELBgwQJMmzbNpvyLL77A/Pnz+UxaC3FAABGRY1worcLIt3+FwXzxY04C4PMH+mNodEDTJxJdA6cOCMjNzUVSUlKD8qSkJOTm5rYoGCIiIkc5mVtuk5j5uSnx5cwExATxiy+1b3Y/c9alSxd8++23DcpXrlyJrl27OiQoIiKilkrq4oO+4Z4AgOlJEfjt2eFMzKhDsLvnbMGCBZgyZQq2b99ufeZs165d2LJlS6NJGxERUVs4V1SJp1YehMUi8Nbk3ogO9MD3jw6GxSIglXJWAeo47O45mzRpEvbu3QtfX1+sWbMGa9asga+vL/bt24cJEya0RoxERERX9dKaoziUpcORbD1e+N8RazkTM+pormmes/j4ePz3v/91dCxERETXzEV5cVZ/F1WLpvEkciq7//euX78eMpkMY8aMsSn/5ZdfYLFYcOuttzosOCIioub656Q4qJUnYLEIvPSnWGeHQ3TN7L6t+cILL8BsNjcoF0LghRdecEhQRERE9vJxVeNf9/TFe/f2g7+H2tnhEF0zu5Oz9PR0xMY2/EYSExOD06dPOyQoIiKiphToa1BSaXR2GEStxu7kTKvV4syZMw3KT58+DVdXV4cERURE1JiiCgM2pObhl2N5qDE1vItDdD2wOzm788478dRTTyEjI8Nadvr0aTz99NO44447HBocERHRpdQKGdzUcmg1csg4CpOuU3Yv36TT6TB27Fjs378foaGhAIALFy5gyJAhWL16NTw9PVsjzhsGl28iIrqyWrMFEomEyRm1K05dvkmr1WL37t3YtGkTDh8+DI1Gg169euHmm29uUSBERETNIZfZfdOHqEOxu+fsUjU1NVCpVJBI+O3FUdhzRkRE1PE48vPb7q8fFosFr776KkJCQuDm5oazZ88CAF566SX8+9//blEwRER0Y9PXmPigP93w7E7OXnvtNXz++ed48803oVQqreU9e/bEp59+6tDgiIjoxrHmYDb6LNiI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",
41
+ "text/plain": [
42
+ "<Figure size 640x480 with 1 Axes>"
43
+ ]
44
+ },
45
+ "metadata": {},
46
+ "output_type": "display_data"
47
+ }
48
+ ],
49
+ "source": [
50
+ "import time\n",
51
+ "import datetime\n",
52
+ "\n",
53
+ "# The results are returned as a triplet of 1D arrays \n",
54
+ "# lims, D, I, where result for query i is in I[lims[i]:lims[i+1]] \n",
55
+ "# (indices of neighbors), D[lims[i]:lims[i+1]] (distances).\n",
56
+ "FPS = 5\n",
57
+ "MIN_DISTANCE = 3\n",
58
+ "lims, D, I = target_indices[0].range_search(hash_vectors, MIN_DISTANCE)\n",
59
+ "\n",
60
+ "min_distances = [min(list(D[lims[i]:lims[i+1]]) or [np.nan]) for i in range(hash_vectors.shape[0])]\n",
61
+ "best_match = [min(list(I[lims[i]:lims[i+1]]) or [np.nan]) for i in range(hash_vectors.shape[0])]\n",
62
+ "\n",
63
+ "x = [(lims[i+1]-lims[i]) * [i] for i in range(hash_vectors.shape[0])]\n",
64
+ "x = [datetime.datetime(1970, 1, 1, 0, 0) + datetime.timedelta(seconds=i/FPS) for j in x for i in j]\n",
65
+ "\n",
66
+ "y = [datetime.datetime(1970, 1, 1, 0, 0) + datetime.timedelta(seconds=i/FPS) for i in I]\n",
67
+ "\n",
68
+ "import matplotlib\n",
69
+ "import matplotlib.pyplot as plt\n",
70
+ "\n",
71
+ "ax = plt.figure()\n",
72
+ "plt.scatter(x, y, s=2*(1-D/MIN_DISTANCE), alpha=1-D/MIN_DISTANCE)\n",
73
+ "plt.xlabel('Time in source video (seconds)')\n",
74
+ "plt.ylabel('Time in target video (seconds)')\n",
75
+ "plt.show()"
76
+ ]
77
+ },
78
+ {
79
+ "cell_type": "code",
80
+ "execution_count": 105,
81
+ "metadata": {},
82
+ "outputs": [
83
+ {
84
+ "data": {
85
+ "text/plain": [
86
+ "datetime.datetime(1970, 1, 1, 1, 0, tzinfo=datetime.timezone.utc)"
87
+ ]
88
+ },
89
+ "execution_count": 105,
90
+ "metadata": {},
91
+ "output_type": "execute_result"
92
+ }
93
+ ],
94
+ "source": [
95
+ "datetime.fromtimestamp(0).replace(tzinfo=timezone.utc)"
96
+ ]
97
+ }
98
+ ],
99
+ "metadata": {
100
+ "interpreter": {
101
+ "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49"
102
+ },
103
+ "kernelspec": {
104
+ "display_name": "Python 3.10.6 64-bit",
105
+ "language": "python",
106
+ "name": "python3"
107
+ },
108
+ "language_info": {
109
+ "codemirror_mode": {
110
+ "name": "ipython",
111
+ "version": 3
112
+ },
113
+ "file_extension": ".py",
114
+ "mimetype": "text/x-python",
115
+ "name": "python",
116
+ "nbconvert_exporter": "python",
117
+ "pygments_lexer": "ipython3",
118
+ "version": "3.10.6"
119
+ },
120
+ "orig_nbformat": 4
121
+ },
122
+ "nbformat": 4,
123
+ "nbformat_minor": 2
124
+ }
app.py CHANGED
@@ -3,6 +3,7 @@ import urllib.request
3
  import logging
4
  import os
5
  import hashlib
 
6
 
7
  import pandas
8
  import gradio as gr
@@ -12,15 +13,9 @@ import imagehash
12
  from PIL import Image
13
 
14
  import numpy as np
15
- import matplotlib
16
- matplotlib.use('SVG')
17
- import matplotlib.pyplot as plt
18
-
19
  import faiss
20
 
21
- logging.basicConfig()
22
- logging.getLogger().setLevel(logging.DEBUG)
23
-
24
 
25
  video_directory = tempfile.gettempdir()
26
 
@@ -33,7 +28,7 @@ def download_video_from_url(url):
33
  logging.info(f"Downloaded video from {url} to {filename}.")
34
  return filename
35
 
36
- def change_ffmpeg_fps(clip, fps=5):
37
  # Hacking the ffmpeg call based on
38
  # https://github.com/Zulko/moviepy/blob/master/moviepy/video/io/ffmpeg_reader.py#L126
39
  import subprocess as sp
@@ -54,7 +49,7 @@ def binary_array_to_uint8s(arr):
54
  bit_string = ''.join(str(1 * x) for l in arr for x in l)
55
  return [int(bit_string[i:i+8], 2) for i in range(0, len(bit_string), 8)]
56
 
57
- def compute_hashes(clip, fps=5):
58
  for index, frame in enumerate(change_ffmpeg_fps(clip, fps).iter_frames()):
59
  hashed = np.array(binary_array_to_uint8s(compute_hash(frame).hash), dtype='uint8')
60
  yield {"frame": 1+index*fps, "hash": hashed}
@@ -80,24 +75,44 @@ def index_hashes_for_video(url):
80
  logging.info(f"Indexed hashes for {index.ntotal} frames to {filename}.index.")
81
  return index
82
 
83
- def compare_videos(url, target):
 
 
 
 
 
 
 
 
 
 
 
84
  video_index = index_hashes_for_video(url)
85
  target_indices = [index_hashes_for_video(x) for x in [target]]
86
 
87
- video_index.make_direct_map()
88
- hash_vectors = np.array([video_index.reconstruct(i) for i in range(video_index.ntotal)])
89
-
90
  # The results are returned as a triplet of 1D arrays
91
  # lims, D, I, where result for query i is in I[lims[i]:lims[i+1]]
92
  # (indices of neighbors), D[lims[i]:lims[i+1]] (distances).
93
- lims, D, I = target_indices[0].range_search(hash_vectors, 20)
94
 
95
- min_distance = [D[lims[i]] for i in range(video_index.ntotal)]
 
 
 
 
 
 
96
 
97
  import matplotlib.pyplot as plt
98
 
99
  ax = plt.figure()
100
- plt.plot(min_distance)
 
 
 
 
101
  return ax
102
 
103
  video_urls = ["https://www.dropbox.com/s/8c89a9aba0w8gjg/Ploumen.mp4?dl=1",
@@ -110,11 +125,17 @@ index_iface = gr.Interface(fn=lambda url: index_hashes_for_video(url).ntotal,
110
  examples=video_urls, cache_examples=True)
111
 
112
  compare_iface = gr.Interface(fn=compare_videos,
113
- inputs=["text", "text"], outputs="plot",
114
  examples=[[x, video_urls[-1]] for x in video_urls[:-1]])
115
 
116
  iface = gr.TabbedInterface([index_iface, compare_iface], ["Index", "Compare"])
117
 
118
  if __name__ == "__main__":
 
 
 
 
 
 
119
  iface.launch()
120
  #iface.launch(auth=("test", "test"), share=True, debug=True)
 
3
  import logging
4
  import os
5
  import hashlib
6
+ import datetime
7
 
8
  import pandas
9
  import gradio as gr
 
13
  from PIL import Image
14
 
15
  import numpy as np
 
 
 
 
16
  import faiss
17
 
18
+ FPS = 5
 
 
19
 
20
  video_directory = tempfile.gettempdir()
21
 
 
28
  logging.info(f"Downloaded video from {url} to {filename}.")
29
  return filename
30
 
31
+ def change_ffmpeg_fps(clip, fps=FPS):
32
  # Hacking the ffmpeg call based on
33
  # https://github.com/Zulko/moviepy/blob/master/moviepy/video/io/ffmpeg_reader.py#L126
34
  import subprocess as sp
 
49
  bit_string = ''.join(str(1 * x) for l in arr for x in l)
50
  return [int(bit_string[i:i+8], 2) for i in range(0, len(bit_string), 8)]
51
 
52
+ def compute_hashes(clip, fps=FPS):
53
  for index, frame in enumerate(change_ffmpeg_fps(clip, fps).iter_frames()):
54
  hashed = np.array(binary_array_to_uint8s(compute_hash(frame).hash), dtype='uint8')
55
  yield {"frame": 1+index*fps, "hash": hashed}
 
75
  logging.info(f"Indexed hashes for {index.ntotal} frames to {filename}.index.")
76
  return index
77
 
78
+ def compare_videos(url, target, MIN_DISTANCE = 3):
79
+ """" The comparison between the target and the original video will be plotted based
80
+ on the matches between the target and the original video over time. The matches are determined
81
+ based on the minimum distance between hashes (as computed by faiss-vectors) before they're considered a match.
82
+
83
+ args:
84
+ - url: url of the source video you want to check for overlap with the target video
85
+ - target: url of the target video
86
+ - MIN_DISTANCE: integer representing the minimum distance between hashes on bit-level before its considered a match
87
+ """
88
+ # TODO: Fix crash if no matches are found
89
+
90
  video_index = index_hashes_for_video(url)
91
  target_indices = [index_hashes_for_video(x) for x in [target]]
92
 
93
+ video_index.make_direct_map() # Make sure the index is indexable
94
+ hash_vectors = np.array([video_index.reconstruct(i) for i in range(video_index.ntotal)]) # Retrieve original indices
95
+
96
  # The results are returned as a triplet of 1D arrays
97
  # lims, D, I, where result for query i is in I[lims[i]:lims[i+1]]
98
  # (indices of neighbors), D[lims[i]:lims[i+1]] (distances).
 
99
 
100
+ lims, D, I = target_indices[0].range_search(hash_vectors, MIN_DISTANCE)
101
+
102
+
103
+
104
+ x = [(lims[i+1]-lims[i]) * [i] for i in range(hash_vectors.shape[0])]
105
+ x = [datetime.datetime(1970, 1, 1, 0, 0) + datetime.timedelta(seconds=i/FPS) for j in x for i in j]
106
+ y = [datetime.datetime(1970, 1, 1, 0, 0) + datetime.timedelta(seconds=i/FPS) for i in I]
107
 
108
  import matplotlib.pyplot as plt
109
 
110
  ax = plt.figure()
111
+ if x and y:
112
+ plt.scatter(x, y, s=2*(1-D/MIN_DISTANCE), alpha=1-D/MIN_DISTANCE)
113
+ plt.xlabel('Time in source video (seconds)')
114
+ plt.ylabel('Time in target video (seconds)')
115
+ plt.show()
116
  return ax
117
 
118
  video_urls = ["https://www.dropbox.com/s/8c89a9aba0w8gjg/Ploumen.mp4?dl=1",
 
125
  examples=video_urls, cache_examples=True)
126
 
127
  compare_iface = gr.Interface(fn=compare_videos,
128
+ inputs=["text", "text", gr.Slider(1, 25, 3, step=1)], outputs="plot",
129
  examples=[[x, video_urls[-1]] for x in video_urls[:-1]])
130
 
131
  iface = gr.TabbedInterface([index_iface, compare_iface], ["Index", "Compare"])
132
 
133
  if __name__ == "__main__":
134
+ import matplotlib
135
+ matplotlib.use('SVG')
136
+
137
+ logging.basicConfig()
138
+ logging.getLogger().setLevel(logging.DEBUG)
139
+
140
  iface.launch()
141
  #iface.launch(auth=("test", "test"), share=True, debug=True)