EVA DATABASE SYSTEM#
AI-Relational Database System | SQL meets Deep Learning

What is EVA?#
EVA is an open-source AI-relational database with first-class support for deep learning models. It aims to support AI-powered database applications that operate on both structured (tables) and unstructured data (videos, text, podcasts, PDFs, etc.) with deep learning models.
EVA accelerates AI pipelines using a collection of optimizations inspired by relational database systems including function caching, sampling, and cost-based operator reordering. It comes with a wide range of models for analyzing unstructured data including image classification, object detection, OCR, face detection, etc. It is fully implemented in Python, and licensed under the Apache license.
EVA supports a AI-oriented query language for analysing unstructured data. Here are some illustrative applications:
If you are wondering why you might need a video database system, start with page on Video Database Systems. It describes how EVA lets users easily make use of deep learning models and how they can reduce money spent on inference on large image or video datasets.
The Getting Started page shows how you can use EVA for different computer vision tasks, and how you can easily extend EVA to support your custom deep learning model in the form of user-defined functions.
The User Guides section contains Jupyter Notebooks that demonstrate how to use various features of EVA. Each notebook includes a link to Google Colab, where you can run the code by yourself.
Key Features#
With EVA, you can easily combine SQL and deep learning models to build next-generation database applications. EVA treats deep learning models as functions similar to traditional SQL functions like SUM().
EVA is extensible by design. You can write an user-defined function (UDF) that wraps arounds your custom deep learning model. In fact, all the built-in models that are included in EVA are written as user-defined functions.
EVA comes with a collection of built-in sampling, caching, and filtering optimizations inspired by relational database systems. These optimizations help speed up queries on large datasets and save money spent on model inference.
Next Steps#
Illustrative EVA Applications#
Traffic Analysis Application using Object Detection Model#
MNIST Digit Recognition using Image Classification Model#
Movie Analysis Application using Face Detection + Emotion Classfication Models#
Community#
Join the EVA community on Slack to ask questions and to share your ideas for improving EVA.

Getting Started#
Part 1: Install EVA#
EVA supports Python (versions >= 3.7). To install EVA, we recommend using the pip package manager:
pip install evadb
Launch EVA server#
EVA is based on a client-server architecture. To launch the EVA server, run the following command on the terminal:
eva_server &
Part 2: Start a Jupyter Notebook Client#
Here is an illustrative Jupyter notebook focusing on MNIST image classification using EVA. The notebook works on Google Colab.
Connect to the EVA server#
To connect to the EVA server in the notebook, use the following Python code:
# allow nested asyncio calls for client to connect with server
import nest_asyncio
nest_asyncio.apply()
from eva.server.db_api import connect
# hostname and port of the server where EVA is running
connection = connect(host = '0.0.0.0', port = 5432)
# cursor allows the notebook client to send queries to the server
cursor = connection.cursor()
Load video for analysis#
Download the MNIST video for analysis.
!wget -nc https://www.dropbox.com/s/yxljxz6zxoqu54v/mnist.mp4
Use the LOAD statement is used to load a video onto a table in EVA server.
cursor.execute('LOAD VIDEO "mnist.mp4" INTO MNISTVideoTable;')
response = cursor.fetch_all()
print(response)
Part 3: Register an user-defined function (UDF)#
User-defined functions allow us to combine SQL with deep learning models. These functions wrap around deep learning models.
Download the user-defined function for classifying MNIST images.
!wget -nc https://raw.githubusercontent.com/georgia-tech-db/eva/master/tutorials/apps/mnist/eva_mnist_udf.py
cursor.execute("""CREATE UDF IF NOT EXISTS MnistCNN
INPUT (data NDARRAY (3, 28, 28))
OUTPUT (label TEXT(2))
TYPE Classification
IMPL 'eva_mnist_udf.py';
""")
response = cursor.fetch_all()
print(response)
Run a query using the newly registered UDF!#
cursor.execute("""SELECT data, MnistCNN(data).label
FROM MNISTVideoTable
WHERE id = 30;""")
response = cursor.fetch_all()
Visualize the output#
The output of the query is visualized in the notebook.
Part 5: Start a Command Line Client#
Besides the notebook interface, EVA also exports a command line interface for querying the server. This interface allows for quick querying from the terminal:
>>> eva_client
eva=# LOAD VIDEO "mnist.mp4" INTO MNISTVid;
@status: ResponseStatus.SUCCESS
@batch:
0 Video successfully added at location: mnist.p4
@query_time: 0.045
eva=# SELECT id, data FROM MNISTVid WHERE id < 1000;
@status: ResponseStatus.SUCCESS
@batch:
mnistvid.id mnistvid.data
0 0 [[[ 0 2 0]\n [0 0 0]\n...
1 1 [[[ 2 2 0]\n [1 1 0]\n...
2 2 [[[ 2 2 0]\n [1 2 2]\n...
.. ...
997 997 [[[ 0 2 0]\n [0 0 0]\n...
998 998 [[[ 0 2 0]\n [0 0 0]\n...
999 999 [[[ 2 2 0]\n [1 1 0]\n...
[1000 rows x 2 columns]
@query_time: 0.216
eva=# exit
List of Notebooks#
This section contains Jupyter Notebooks that demonstrate how to use various features of EVA. Each notebook includes a link to Google Colab, where you can run the code by yourself.
Start EVA Server#
![]() |
![]() |
![]() |
Launch EVA server#
We use this notebook for launching the EVA server.
## Install EVA package if needed
%pip install "evadb" --quiet
import os
import time
from psutil import process_iter
from signal import SIGTERM
import re
import itertools
def shell(command):
print(command)
os.system(command)
def stop_eva_server():
for proc in process_iter():
if proc.name() == "eva_server":
proc.send_signal(SIGTERM)
def is_eva_server_running():
for proc in process_iter():
if proc.name() == "eva_server":
return True
return False
def launch_eva_server():
# Stop EVA server if it is running
# stop_eva_server()
os.environ['GPU_DEVICES'] = '0'
# Start EVA server
shell("nohup eva_server > eva.log 2>&1 &")
last_few_lines_count = 3
try:
with open('eva.log', 'r') as f:
for lines in itertools.zip_longest(*[f]*last_few_lines_count):
print(lines)
except FileNotFoundError:
pass
# Wait for server to start
time.sleep(10)
def connect_to_server():
from eva.server.db_api import connect
%pip install nest_asyncio --quiet
import nest_asyncio
nest_asyncio.apply()
status = is_eva_server_running()
if status == False:
launch_eva_server()
# Connect client with server
connection = connect(host = '127.0.0.1', port = 5432)
cursor = connection.cursor()
return cursor
# Launch server
launch_eva_server()
[notice] A new release of pip is available: 23.0.1 -> 23.1.2
[notice] To update, run: pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
nohup eva_server > eva.log 2>&1 &
MNIST TUTORIAL#
![]() |
![]() |
![]() |
Start EVA server#
We are reusing the start server notebook for launching the EVA server.
!wget -nc "https://raw.githubusercontent.com/georgia-tech-db/eva/master/tutorials/00-start-eva-server.ipynb"
%run 00-start-eva-server.ipynb
cursor = connect_to_server()
File ‘00-start-eva-server.ipynb’ already there; not retrieving.
[notice] A new release of pip is available: 23.0.1 -> 23.1.2
[notice] To update, run: pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
nohup eva_server > eva.log 2>&1 &
[notice] A new release of pip is available: 23.0.1 -> 23.1.2
[notice] To update, run: pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
Downloading the videos#
# Getting MNIST as a video
!wget -nc https://www.dropbox.com/s/yxljxz6zxoqu54v/mnist.mp4
# Getting a udf
!wget -nc https://raw.githubusercontent.com/georgia-tech-db/eva/master/tutorials/apps/mnist/eva_mnist_udf.py
File ‘mnist.mp4’ already there; not retrieving.
File ‘eva_mnist_udf.py’ already there; not retrieving.
Upload the video for analysis#
cursor.execute('DROP TABLE IF EXISTS MNISTVid')
response = cursor.fetch_all()
response.as_df()
cursor.execute("LOAD VIDEO 'mnist.mp4' INTO MNISTVid")
response = cursor.fetch_all()
response.as_df()
0 | |
---|---|
0 | Number of loaded VIDEO: 1 |
Visualize Video#
from IPython.display import Video
Video("mnist.mp4", embed=True)
Create an user-defined function (UDF) for analyzing the frames#
cursor.execute("""CREATE UDF IF NOT EXISTS
MnistCNN
INPUT (data NDARRAY (3, 28, 28))
OUTPUT (label TEXT(2))
TYPE Classification
IMPL 'eva_mnist_udf.py'
""")
response = cursor.fetch_all()
response.as_df()
0 | |
---|---|
0 | UDF MnistCNN successfully added to the database. |
Run the Image Classification UDF on video#
cursor.execute("""SELECT data, MnistCNN(data).label
FROM MNISTVid
WHERE id = 30 OR id = 50 OR id = 70 OR id = 0 OR id = 140""")
response = cursor.fetch_all()
response.as_df()
mnistvid.data | mnistcnn.label | |
---|---|---|
0 | [[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], ... | 6 |
1 | [[[2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], ... | 2 |
2 | [[[13, 13, 13], [2, 2, 2], [2, 2, 2], [13, 13,... | 3 |
3 | [[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], ... | 7 |
4 | [[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], ... | 5 |
Visualize output of query on the video#
# !pip install matplotlib
import matplotlib.pyplot as plt
import numpy as np
# create figure (fig), and array of axes (ax)
fig, ax = plt.subplots(nrows=1, ncols=5, figsize=[6,8])
df = response.batch.frames
for axi in ax.flat:
idx = np.random.randint(len(df))
img = df['mnistvid.data'].iloc[idx]
label = df['mnistcnn.label'].iloc[idx]
axi.imshow(img)
axi.set_title(f'label: {label}')
plt.show()

Object Detection Tutorial#
![]() |
![]() |
![]() |
Start EVA server#
We are reusing the start server notebook for launching the EVA server.
!wget -nc "https://raw.githubusercontent.com/georgia-tech-db/eva/master/tutorials/00-start-eva-server.ipynb"
%run 00-start-eva-server.ipynb
cursor = connect_to_server()
File ‘00-start-eva-server.ipynb’ already there; not retrieving.
[notice] A new release of pip is available: 23.0.1 -> 23.1.2
[notice] To update, run: pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
nohup eva_server > eva.log 2>&1 &
[notice] A new release of pip is available: 23.0.1 -> 23.1.2
[notice] To update, run: pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
Download the Videos#
# Getting the video files
!wget -nc "https://www.dropbox.com/s/k00wge9exwkfxz6/ua_detrac.mp4?raw=1" -O ua_detrac.mp4
File ‘ua_detrac.mp4’ already there; not retrieving.
Load the surveillance videos for analysis#
We use regular expression to load all the videos into the table#
cursor.execute('DROP TABLE IF EXISTS ObjectDetectionVideos')
response = cursor.fetch_all()
response.as_df()
cursor.execute('LOAD VIDEO "ua_detrac.mp4" INTO ObjectDetectionVideos;')
response = cursor.fetch_all()
response.as_df()
0 | |
---|---|
0 | Number of loaded VIDEO: 1 |
Visualize Video#
from IPython.display import Video
Video("ua_detrac.mp4", embed=True)
Register YOLO Object Detector an an User-Defined Function (UDF) in EVA#
cursor.execute("""
CREATE UDF IF NOT EXISTS Yolo
TYPE ultralytics
'model' 'yolov8m.pt';
""")
response = cursor.fetch_all()
response.as_df()
0 | |
---|---|
0 | UDF Yolo already exists, nothing added. |
Run Object Detector on the video#
cursor.execute("""SELECT id, Yolo(data)
FROM ObjectDetectionVideos
WHERE id < 20""")
response = cursor.fetch_all()
response.as_df()
objectdetectionvideos.id | yolo.labels | yolo.bboxes | yolo.scores | |
---|---|---|---|---|
0 | 0 | [car, car, car, car, car, car, person, car, ca... | [[829.0, 277.0, 960.0, 360.0], [615.0, 216.0, ... | [0.91, 0.86, 0.85, 0.83, 0.76, 0.73, 0.72, 0.7... |
1 | 1 | [car, car, car, car, car, car, car, car, car, ... | [[832.0, 278.0, 960.0, 361.0], [616.0, 216.0, ... | [0.92, 0.85, 0.84, 0.83, 0.78, 0.76, 0.76, 0.7... |
2 | 2 | [car, car, car, car, car, car, car, person, ca... | [[836.0, 279.0, 960.0, 362.0], [618.0, 216.0, ... | [0.92, 0.84, 0.84, 0.82, 0.81, 0.75, 0.73, 0.7... |
3 | 3 | [car, car, car, car, car, car, car, car, car, ... | [[839.0, 280.0, 960.0, 363.0], [619.0, 217.0, ... | [0.91, 0.84, 0.82, 0.8, 0.8, 0.75, 0.74, 0.72,... |
4 | 4 | [car, car, car, car, car, car, car, car, car, ... | [[843.0, 281.0, 960.0, 364.0], [621.0, 218.0, ... | [0.9, 0.85, 0.83, 0.8, 0.76, 0.73, 0.72, 0.72,... |
5 | 5 | [car, car, car, car, car, car, person, car, ca... | [[847.0, 282.0, 960.0, 363.0], [623.0, 218.0, ... | [0.89, 0.86, 0.84, 0.8, 0.78, 0.74, 0.72, 0.72... |
6 | 6 | [car, car, car, car, car, car, car, person, ca... | [[851.0, 283.0, 959.0, 360.0], [625.0, 219.0, ... | [0.89, 0.87, 0.85, 0.81, 0.79, 0.73, 0.72, 0.7... |
7 | 7 | [car, car, car, car, car, car, car, car, car, ... | [[855.0, 284.0, 960.0, 357.0], [626.0, 220.0, ... | [0.9, 0.87, 0.84, 0.83, 0.83, 0.79, 0.73, 0.67... |
8 | 8 | [car, car, car, car, car, car, person, car, ca... | [[859.0, 285.0, 960.0, 357.0], [628.0, 221.0, ... | [0.89, 0.88, 0.83, 0.82, 0.79, 0.71, 0.68, 0.6... |
9 | 9 | [car, car, car, car, car, car, car, person, ca... | [[863.0, 286.0, 960.0, 357.0], [630.0, 222.0, ... | [0.88, 0.87, 0.84, 0.82, 0.8, 0.75, 0.74, 0.74... |
10 | 10 | [car, car, car, car, car, car, car, person, ca... | [[632.0, 223.0, 744.0, 284.0], [867.0, 287.0, ... | [0.88, 0.88, 0.85, 0.82, 0.8, 0.79, 0.76, 0.71... |
11 | 11 | [car, car, car, car, car, car, person, car, ca... | [[871.0, 289.0, 960.0, 356.0], [634.0, 223.0, ... | [0.9, 0.9, 0.85, 0.8, 0.79, 0.77, 0.69, 0.68, ... |
12 | 12 | [car, car, car, car, car, car, car, person, ca... | [[636.0, 223.0, 750.0, 287.0], [875.0, 290.0, ... | [0.9, 0.88, 0.83, 0.81, 0.78, 0.78, 0.78, 0.67... |
13 | 13 | [car, car, car, car, car, car, person, car, ca... | [[171.0, 409.0, 291.0, 539.0], [637.0, 224.0, ... | [0.9, 0.89, 0.89, 0.83, 0.81, 0.81, 0.72, 0.71... |
14 | 14 | [car, car, car, car, car, car, person, car, ca... | [[174.0, 405.0, 294.0, 538.0], [885.0, 291.0, ... | [0.9, 0.89, 0.88, 0.84, 0.82, 0.81, 0.75, 0.72... |
15 | 15 | [car, car, car, car, car, car, person, car, ca... | [[888.0, 293.0, 960.0, 355.0], [177.0, 400.0, ... | [0.89, 0.88, 0.87, 0.84, 0.82, 0.78, 0.76, 0.7... |
16 | 16 | [car, car, car, car, car, car, car, person, ca... | [[893.0, 293.0, 960.0, 355.0], [180.0, 396.0, ... | [0.88, 0.88, 0.87, 0.82, 0.81, 0.76, 0.75, 0.7... |
17 | 17 | [car, car, car, car, car, car, car, person, ca... | [[182.0, 392.0, 296.0, 519.0], [897.0, 294.0, ... | [0.9, 0.89, 0.87, 0.83, 0.82, 0.78, 0.72, 0.69... |
18 | 18 | [car, car, car, car, car, car, car, person, mo... | [[901.0, 295.0, 960.0, 356.0], [647.0, 225.0, ... | [0.88, 0.88, 0.83, 0.82, 0.8, 0.78, 0.75, 0.7,... |
19 | 19 | [car, car, car, car, car, person, car, car, ca... | [[648.0, 226.0, 770.0, 293.0], [906.0, 297.0, ... | [0.89, 0.87, 0.81, 0.8, 0.78, 0.77, 0.73, 0.72... |
Visualizing output of the Object Detector on the video#
import cv2
from pprint import pprint
from matplotlib import pyplot as plt
def annotate_video(detections, input_video_path, output_video_path):
color1=(207, 248, 64)
color2=(255, 49, 49)
thickness=4
vcap = cv2.VideoCapture(input_video_path)
width = int(vcap.get(3))
height = int(vcap.get(4))
fps = vcap.get(5)
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') #codec
video=cv2.VideoWriter(output_video_path, fourcc, fps, (width,height))
frame_id = 0
# Capture frame-by-frame
# ret = 1 if the video is captured; frame is the image
ret, frame = vcap.read()
while ret:
df = detections
df = df[['yolo.bboxes', 'yolo.labels']][df.index == frame_id]
if df.size:
dfLst = df.values.tolist()
for bbox, label in zip(dfLst[0][0], dfLst[0][1]):
x1, y1, x2, y2 = bbox
x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
# object bbox
frame=cv2.rectangle(frame, (x1, y1), (x2, y2), color1, thickness)
# object label
cv2.putText(frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, color1, thickness)
# frame label
cv2.putText(frame, 'Frame ID: ' + str(frame_id), (700, 500), cv2.FONT_HERSHEY_SIMPLEX, 1.2, color2, thickness)
video.write(frame)
# Stop after twenty frames (id < 20 in previous query)
if frame_id == 20:
break
# Show every fifth frame
if frame_id % 5 == 0:
plt.imshow(frame)
plt.show()
frame_id+=1
ret, frame = vcap.read()
video.release()
vcap.release()
from ipywidgets import Video, Image
input_path = 'ua_detrac.mp4'
output_path = 'video.mp4'
dataframe = response.as_df()
annotate_video(dataframe, input_path, output_path)
Video.from_file(output_path)




Dropping an User-Defined Function (UDF)#
cursor.execute("DROP UDF IF EXISTS Yolo;")
response = cursor.fetch_all()
response.as_df()
0 | |
---|---|
0 | UDF Yolo successfully dropped |
EMOTION ANALYSIS#
![]() |
![]() |
![]() |
Start EVA Server#
We are reusing the start server notebook for launching the EVA server
!wget -nc "https://raw.githubusercontent.com/georgia-tech-db/eva/master/tutorials/00-start-eva-server.ipynb"
%run 00-start-eva-server.ipynb
cursor = connect_to_server()
File ‘00-start-eva-server.ipynb’ already there; not retrieving.
[notice] A new release of pip is available: 23.0.1 -> 23.1.2
[notice] To update, run: pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
nohup eva_server > eva.log 2>&1 &
[notice] A new release of pip is available: 23.0.1 -> 23.1.2
[notice] To update, run: pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
Video Files#
getting some video files to test
# A video of a happy person
!wget -nc "https://www.dropbox.com/s/gzfhwmib7u804zy/defhappy.mp4?raw=1" -O defhappy.mp4
# Adding Emotion detection
!wget -nc https://raw.githubusercontent.com/georgia-tech-db/eva/master/eva/udfs/emotion_detector.py
# Adding Face Detector
!wget -nc https://raw.githubusercontent.com/georgia-tech-db/eva/master/eva/udfs/face_detector.py
File ‘defhappy.mp4’ already there; not retrieving.
File ‘emotion_detector.py’ already there; not retrieving.
File ‘face_detector.py’ already there; not retrieving.
Adding the video file to EVADB for analysis#
cursor.execute('DROP TABLE IF EXISTS HAPPY')
response = cursor.fetch_all()
response.as_df()
cursor.execute('LOAD VIDEO "defhappy.mp4" INTO HAPPY')
response = cursor.fetch_all()
response.as_df()
0 | |
---|---|
0 | Number of loaded VIDEO: 1 |
Visualize Video#
from IPython.display import Video
Video("defhappy.mp4", height=450, width=800, embed=True)
Create an user-defined function(UDF) for analyzing the frames#
cursor.execute("""CREATE UDF IF NOT EXISTS EmotionDetector
INPUT (frame NDARRAY UINT8(3, ANYDIM, ANYDIM))
OUTPUT (labels NDARRAY STR(ANYDIM), scores NDARRAY FLOAT32(ANYDIM))
TYPE Classification IMPL 'emotion_detector.py';
""")
response = cursor.fetch_all()
response.as_df()
cursor.execute("""CREATE UDF IF NOT EXISTS FaceDetector
INPUT (frame NDARRAY UINT8(3, ANYDIM, ANYDIM))
OUTPUT (bboxes NDARRAY FLOAT32(ANYDIM, 4),
scores NDARRAY FLOAT32(ANYDIM))
TYPE FaceDetection
IMPL 'face_detector.py';
""")
response = cursor.fetch_all()
response.as_df()
0 | |
---|---|
0 | UDF FaceDetector successfully added to the dat... |
Run the Face Detection UDF on video#
cursor.execute("""SELECT id, FaceDetector(data)
FROM HAPPY WHERE id<10""")
response = cursor.fetch_all()
response.as_df()
happy.id | facedetector.bboxes | facedetector.scores | |
---|---|---|---|
0 | 0 | [[502, 94, 762, 435], [238, 296, 325, 398]] | [0.99990165, 0.79820246] |
1 | 1 | [[501, 96, 763, 435]] | [0.999918] |
2 | 2 | [[504, 97, 766, 437]] | [0.9999138] |
3 | 3 | [[498, 90, 776, 446]] | [0.99996686] |
4 | 4 | [[496, 99, 767, 444]] | [0.9999982] |
5 | 5 | [[499, 87, 777, 448], [236, 305, 324, 407]] | [0.9999136, 0.8369736] |
6 | 6 | [[500, 89, 778, 449]] | [0.9999131] |
7 | 7 | [[501, 89, 781, 452]] | [0.9999124] |
8 | 8 | [[503, 90, 783, 450]] | [0.99994683] |
9 | 9 | [[508, 87, 786, 447]] | [0.999949] |
Run the Emotion Detection UDF on the outputs of the Face Detection UDF#
cursor.execute("""SELECT id, bbox, EmotionDetector(Crop(data, bbox))
FROM HAPPY JOIN LATERAL UNNEST(FaceDetector(data)) AS Face(bbox, conf)
WHERE id < 15;""")
response = cursor.fetch_all()
response.as_df()
happy.id | Face.bbox | emotiondetector.labels | emotiondetector.scores | |
---|---|---|---|---|
0 | 0 | [502, 94, 762, 435] | happy | 0.999642 |
1 | 0 | [238, 296, 325, 398] | neutral | 0.780949 |
2 | 1 | [501, 96, 763, 435] | happy | 0.999644 |
3 | 2 | [504, 97, 766, 437] | happy | 0.999668 |
4 | 3 | [498, 90, 776, 446] | happy | 0.999654 |
5 | 4 | [496, 99, 767, 444] | happy | 0.999649 |
6 | 5 | [499, 87, 777, 448] | happy | 0.999710 |
7 | 5 | [236, 305, 324, 407] | neutral | 0.760779 |
8 | 6 | [500, 89, 778, 449] | happy | 0.999671 |
9 | 7 | [501, 89, 781, 452] | happy | 0.999671 |
10 | 8 | [503, 90, 783, 450] | happy | 0.999689 |
11 | 9 | [508, 87, 786, 447] | happy | 0.999691 |
12 | 10 | [505, 86, 788, 452] | happy | 0.999729 |
13 | 10 | [235, 309, 322, 411] | neutral | 0.407872 |
14 | 11 | [514, 85, 790, 454] | happy | 0.999745 |
15 | 12 | [514, 86, 790, 454] | happy | 0.999729 |
16 | 13 | [515, 87, 790, 454] | happy | 0.999718 |
17 | 14 | [516, 86, 792, 455] | happy | 0.999739 |
import cv2
from pprint import pprint
from matplotlib import pyplot as plt
def annotate_video(detections, input_video_path, output_video_path):
color1=(207, 248, 64)
color2=(255, 49, 49)
thickness=4
vcap = cv2.VideoCapture(input_video_path)
width = int(vcap.get(3))
height = int(vcap.get(4))
fps = vcap.get(5)
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') #codec
video=cv2.VideoWriter(output_video_path, fourcc, fps, (width,height))
frame_id = 0
# Capture frame-by-frame
# ret = 1 if the video is captured; frame is the image
ret, frame = vcap.read()
while ret:
df = detections
df = df[['Face.bbox', 'emotiondetector.labels', 'emotiondetector.scores']][df.index == frame_id]
if df.size:
x1, y1, x2, y2 = df['Face.bbox'].values[0]
label = df['emotiondetector.labels'].values[0]
score = df['emotiondetector.scores'].values[0]
x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
# object bbox
frame=cv2.rectangle(frame, (x1, y1), (x2, y2), color1, thickness)
# object label
cv2.putText(frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, color1, thickness)
# object score
cv2.putText(frame, str(round(score, 5)), (x1+120, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, color1, thickness)
# frame label
cv2.putText(frame, 'Frame ID: ' + str(frame_id), (700, 500), cv2.FONT_HERSHEY_SIMPLEX, 1.2, color2, thickness)
video.write(frame)
# Show every fifth frame
if frame_id % 5 == 0:
plt.imshow(frame)
plt.show()
frame_id+=1
ret, frame = vcap.read()
video.release()
vcap.release()
from ipywidgets import Video, Image
input_path = 'defhappy.mp4'
output_path = 'video.mp4'
dataframe = response.as_df()
annotate_video(dataframe, input_path, output_path)




Image Segmentation Tutorial#
![]() |
![]() |
![]() |
Start EVA server#
We are reusing the start server notebook for launching the EVA server.
!wget -nc "https://raw.githubusercontent.com/georgia-tech-db/eva/master/tutorials/00-start-eva-server.ipynb"
!pip install timm
%run 00-start-eva-server.ipynb
stop_eva_server()
cursor = connect_to_server()
File ‘00-start-eva-server.ipynb’ already there; not retrieving.
Requirement already satisfied: timm in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (0.6.13)
Requirement already satisfied: huggingface-hub in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from timm) (0.14.1)
Requirement already satisfied: pyyaml in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from timm) (6.0)
Requirement already satisfied: torchvision in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from timm) (0.14.0)
Requirement already satisfied: torch>=1.7 in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from timm) (1.13.0)
Requirement already satisfied: nvidia-cuda-runtime-cu11==11.7.99 in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from torch>=1.7->timm) (11.7.99)
Requirement already satisfied: typing-extensions in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from torch>=1.7->timm) (4.4.0)
Requirement already satisfied: nvidia-cuda-nvrtc-cu11==11.7.99 in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from torch>=1.7->timm) (11.7.99)
Requirement already satisfied: nvidia-cublas-cu11==11.10.3.66 in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from torch>=1.7->timm) (11.10.3.66)
Requirement already satisfied: nvidia-cudnn-cu11==8.5.0.96 in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from torch>=1.7->timm) (8.5.0.96)
Requirement already satisfied: wheel in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from nvidia-cublas-cu11==11.10.3.66->torch>=1.7->timm) (0.38.4)
Requirement already satisfied: setuptools in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from nvidia-cublas-cu11==11.10.3.66->torch>=1.7->timm) (65.6.0)
Requirement already satisfied: packaging>=20.9 in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from huggingface-hub->timm) (23.0)
Requirement already satisfied: requests in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from huggingface-hub->timm) (2.28.1)
Requirement already satisfied: fsspec in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from huggingface-hub->timm) (2023.4.0)
Requirement already satisfied: filelock in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from huggingface-hub->timm) (3.8.0)
Requirement already satisfied: tqdm>=4.42.1 in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from huggingface-hub->timm) (4.64.1)
Requirement already satisfied: pillow!=8.3.*,>=5.3.0 in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from torchvision->timm) (9.0.1)
Requirement already satisfied: numpy in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from torchvision->timm) (1.23.4)
Requirement already satisfied: certifi>=2017.4.17 in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from requests->huggingface-hub->timm) (2022.9.24)
Requirement already satisfied: charset-normalizer<3,>=2 in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from requests->huggingface-hub->timm) (2.1.1)
Requirement already satisfied: idna<4,>=2.5 in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from requests->huggingface-hub->timm) (3.4)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in /home/jarulraj3/eva/test_evadb/lib/python3.10/site-packages (from requests->huggingface-hub->timm) (1.26.12)
[notice] A new release of pip is available: 23.0.1 -> 23.1.2
[notice] To update, run: pip install --upgrade pip
[notice] A new release of pip is available: 23.0.1 -> 23.1.2
[notice] To update, run: pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
nohup eva_server > eva.log 2>&1 &
[notice] A new release of pip is available: 23.0.1 -> 23.1.2
[notice] To update, run: pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
Download the Videos#
# # Getting the video files
!wget -nc "https://www.dropbox.com/s/k00wge9exwkfxz6/ua_detrac.mp4?raw=1" -O ua_detrac.mp4
File ‘ua_detrac.mp4’ already there; not retrieving.
Load sample video from DAVIS dataset for analysis#
cursor.execute('DROP TABLE IF EXISTS VideoForSegmentation;')
response = cursor.fetch_all()
response.as_df()
cursor.execute('LOAD VIDEO "ua_detrac.mp4" INTO VideoForSegmentation')
response = cursor.fetch_all()
response.as_df()
0 | |
---|---|
0 | Number of loaded VIDEO: 1 |
Visualize Video#
from IPython.display import Video
Video("ua_detrac.mp4", embed=True)
Register Hugging Face Segmentation Model as an User-Defined Function (UDF) in EVA#
### Using HuggingFace with EVA requires specifying the task
### The task here is 'image-segmentation'
### The model is 'facebook/detr-resnet-50-panoptic'
cursor.execute("""CREATE UDF IF NOT EXISTS HFSegmentation
TYPE HuggingFace
'task' 'image-segmentation'
'model' 'facebook/detr-resnet-50-panoptic'
""")
response = cursor.fetch_all()
response.as_df()
0 | |
---|---|
0 | UDF HFSegmentation successfully added to the d... |
Run Image Segmentation on the video#
cursor.execute("""SELECT HFSegmentation(data)
FROM VideoForSegmentation SAMPLE 5
WHERE id < 20""")
response = cursor.fetch_all()
response.as_df()
hfsegmentation.score | hfsegmentation.label | hfsegmentation.mask | |
---|---|---|---|
0 | [0.906596, 0.989519, 0.960914, 0.923789, 0.960... | [motorcycle, motorcycle, person, car, car, per... | [<PIL.Image.Image image mode=L size=960x540 at... |
1 | [0.985118, 0.963139, 0.963819, 0.960939, 0.926... | [motorcycle, person, car, car, person, bridge,... | [<PIL.Image.Image image mode=L size=960x540 at... |
2 | [0.989573, 0.900049, 0.966254, 0.96056, 0.9388... | [motorcycle, person, person, car, car, car, pe... | [<PIL.Image.Image image mode=L size=960x540 at... |
3 | [0.913261, 0.949733, 0.943763, 0.98639, 0.9744... | [truck, person, car, car, car, car, car, perso... | [<PIL.Image.Image image mode=L size=960x540 at... |
Visualizing output of the Image Segmenter on the video#
import numpy as np
from PIL import Image
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
import cv2
def get_color_mapping(all_labels):
unique_labels = set(label for labels in all_labels for label in labels)
num_colors = len(unique_labels)
colormap = plt.colormaps["tab20"]
colors = [colormap(i % 20)[:3] for i in range(num_colors)]
colors = [tuple(int(c * 255) for c in color) for color in colors]
color_mapping = {label: color for label, color in zip(unique_labels, colors)}
return color_mapping
def annotate_single_frame(frame, segments, labels, color_mapping):
overlay = np.zeros_like(frame)
# Overlay segments
for mask, label in zip(segments, labels):
mask_np = np.array(mask).astype(bool)
overlay[mask_np] = color_mapping[label]
# Combine original frame with overlay
new_frame = Image.blend(
Image.fromarray(frame.astype(np.uint8)),
Image.fromarray(overlay.astype(np.uint8)),
alpha=0.5,
)
return new_frame
def annotate_video(segmentations, input_video_path, output_video_path, model_name = 'hfsegmentation'):
all_segments = segmentations[f'{model_name}.mask']
all_labels = segmentations[f'{model_name}.label']
color_mapping = get_color_mapping(all_labels)
vcap = cv2.VideoCapture(input_video_path)
width = int(vcap.get(3))
height = int(vcap.get(4))
fps = vcap.get(5)
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') #codec
video=cv2.VideoWriter(output_video_path, fourcc, fps, (width,height))
frame_id = 0
ret, frame = vcap.read()
while ret and frame_id < len(all_segments):
segments = all_segments[frame_id]
labels = all_labels[frame_id]
new_frame = annotate_single_frame(frame, segments, labels, color_mapping)
video.write(np.array(new_frame))
if frame_id % 5 == 0:
legend_patches = [mpatches.Patch(color=np.array(color_mapping[label])/255, label=label) for label in set(labels)]
plt.imshow(new_frame)
plt.legend(handles=legend_patches, bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)
plt.axis('off')
plt.tight_layout()
plt.show()
frame_id += 1
ret, frame = vcap.read()
video.release()
vcap.release()
from ipywidgets import Video
input_path = 'ua_detrac.mp4'
output_path = 'video.mp4'
dataframe = response.as_df()
annotate_video(dataframe, input_path, output_path)
Video.from_file(output_path)

Dropping an User-Defined Function (UDF)#
cursor.execute("DROP UDF HFSegmentation;")
response = cursor.fetch_all()
response.as_df()
0 | |
---|---|
0 | UDF HFSegmentation successfully dropped |
ChatGPT Tutorial#
![]() |
![]() |
![]() |
Start EVA server#
We are reusing the start server notebook for launching the EVA server
!wget -nc "https://raw.githubusercontent.com/georgia-tech-db/eva/master/tutorials/00-start-eva-server.ipynb"
%run 00-start-eva-server.ipynb
cursor = connect_to_server()
File ‘00-start-eva-server.ipynb’ already there; not retrieving.
[notice] A new release of pip is available: 23.0.1 -> 23.1.2
[notice] To update, run: pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
nohup eva_server > eva.log 2>&1 &
[notice] A new release of pip is available: 23.0.1 -> 23.1.2
[notice] To update, run: pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
Download News Video and ChatGPT UDF#
# Download News Video
!wget -nc "https://www.dropbox.com/s/rfm1kds2mv77pca/russia_ukraine.mp4?dl=0" -O russia_ukraine.mp4
# Download ChatGPT UDF if needed
!wget -nc https://raw.githubusercontent.com/georgia-tech-db/eva/master/eva/udfs/chatgpt.py -O chatgpt.py
File ‘russia_ukraine.mp4’ already there; not retrieving.
File ‘chatgpt.py’ already there; not retrieving.
Visualize Video#
from IPython.display import Video
Video("russia_ukraine.mp4", height=450, width=800, embed=True)
Set your OpenAI API key here#
from eva.configuration.configuration_manager import ConfigurationManager
import os
# Assuming that the key is stored as an environment variable
open_ai_key = os.environ.get('OPENAI_KEY')
ConfigurationManager().update_value("third_party", "openai_api_key", open_ai_key)
# Drop the UDF if it already exists
drop_udf_query = f"DROP UDF IF EXISTS ChatGPT;"
cursor.execute(drop_udf_query)
response = cursor.fetch_all()
response.as_df()
# Register the ChatGPT UDF in EVA
create_udf_query = f"""CREATE UDF ChatGPT
IMPL 'chatgpt.py' """
cursor.execute(create_udf_query)
response = cursor.fetch_all()
response.as_df()
0 | |
---|---|
0 | UDF ChatGPT successfully added to the database. |
Run the ChatGPT UDF#
#load the video
cursor.execute("LOAD VIDEO 'russia_ukraine.mp4' INTO VIDEOS;")
response = cursor.fetch_all()
response.as_df()
0 | |
---|---|
0 | Number of loaded VIDEO: 1 |
# Drop the Text Summarization UDF if needed
cursor.execute("DROP UDF IF EXISTS SpeechRecognizer;")
response = cursor.fetch_all()
response.as_df()
# Create a Text Summarization UDF using Hugging Face
text_summarizer_udf_creation = """
CREATE UDF SpeechRecognizer
TYPE HuggingFace
'task' 'automatic-speech-recognition'
'model' 'openai/whisper-base';
"""
cursor.execute(text_summarizer_udf_creation)
response = cursor.fetch_all()
response.as_df()
0 | |
---|---|
0 | UDF SpeechRecognizer successfully added to the... |
# Drop the table if needed
cursor.execute("DROP TABLE IF EXISTS TEXT_SUMMARY;")
response = cursor.fetch_all()
response.as_df()
# Create a materialized view of the text summarization output
text_summarization_query = """
CREATE MATERIALIZED VIEW
TEXT_SUMMARY(text) AS
SELECT SpeechRecognizer(audio) FROM VIDEOS;
"""
cursor.execute(text_summarization_query)
response = cursor.fetch_all()
response.as_df()
# Run ChatGPT over the Text Summary extracted by Whisper
chatgpt_udf = """
SELECT ChatGPT('Is this video summary related to Ukraine russia war',text)
FROM TEXT_SUMMARY;
"""
cursor.execute(chatgpt_udf)
response = cursor.fetch_all()
response.as_df()
chatgpt.response | |
---|---|
0 | No, this video summary is not related to the U... |
1 | Yes, the video summary is related to the Ukrai... |
Check if it works on an SNL Video#
# Download Entertainment Video
!wget -nc "https://www.dropbox.com/s/u66im8jw2s1dmuw/snl.mp4?dl=0" -O snl.mp4
cursor.execute("DROP TABLE IF EXISTS SNL_VIDEO;")
response = cursor.fetch_all()
response.as_df()
cursor.execute("LOAD VIDEO 'snl.mp4' INTO SNL_VIDEO;")
response = cursor.fetch_all()
response.as_df()
File ‘snl.mp4’ already there; not retrieving.
0 | |
---|---|
0 | Number of loaded VIDEO: 1 |
from IPython.display import Video
Video("snl.mp4", height=450, width=800, embed=True)