Skip to content

Commit 248c634

Browse files
authored
Merge pull request #21 from aperture-data/release-0.0.11
Release 0.0.11
2 parents 050ae46 + ecb5c07 commit 248c634

File tree

8 files changed

+347
-19
lines changed

8 files changed

+347
-19
lines changed

aperturedb/BBoxLoader.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,14 @@ def generate_batch(self, bbox_data):
136136
}
137137

138138
if "properties" in data:
139-
ai["AddBoundingBox"]["properties"] = data[CSVParser.PROPERTIES]
139+
props = data[CSVParser.PROPERTIES]
140+
if "_label" in props:
141+
ai["AddBoundingBox"]["label"] = props["_label"]
142+
props.pop("_label")
143+
144+
# Check if props is not empty after removing "_label"
145+
if props:
146+
ai["AddBoundingBox"]["properties"] = props
140147

141148
q.append(ai)
142149

aperturedb/ImageDownloader.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class ImageDownloaderCSV(CSVParser.CSVParser):
2626
def __init__(self, filename, check_image=True):
2727

2828
self.has_filename = False
29-
self.check_image = check_image
29+
self.check_img = check_image
3030

3131
super().__init__(filename)
3232

aperturedb/Images.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
from matplotlib.collections import PatchCollection
1212
from matplotlib.patches import Polygon
1313

14+
from aperturedb import Status
15+
1416
class Constraints(object):
1517

1618
def __init__(self):
@@ -88,7 +90,7 @@ def __init__(self, db, batch_size=100):
8890
self.display_limit = 20
8991

9092
self.img_id_prop = "_uniqueid"
91-
self.bbox_label_prop = "label"
93+
self.bbox_label_prop = "_label"
9294

9395
def __retrieve_batch(self, index):
9496

@@ -152,15 +154,19 @@ def __get_bounding_boxes_polygons(self, index):
152154
"blobs": False,
153155
}
154156
}, {
155-
"FindEntity": {
157+
"FindBlob": {
156158
"is_connected_to": {
157159
"ref": 1
158160
},
161+
"constraints": {
162+
"type": ["==", "segmentation"]
163+
},
159164
"blobs": True,
160165
}
161166
}]
162167

163168
res, polygons = self.db_connector.query(query)
169+
164170
ret_poly.append(polygons)
165171

166172
uniqueid_str = str(uniqueid)
@@ -225,9 +231,7 @@ def __retrieve_bounding_boxes(self, index):
225231
"_ref": 2,
226232
"blobs": False,
227233
"coordinates": True,
228-
"results": {
229-
"list": [self.bbox_label_prop],
230-
}
234+
"labels": True,
231235
}
232236
}]
233237

@@ -458,18 +462,12 @@ def display(self, show_bboxes=False, show_segmentation=False, limit=None):
458462

459463
def get_props_names(self):
460464

461-
query = [ {
462-
"GetSchema": {
463-
"type" : "entities"
464-
}
465-
}]
466-
467-
res, images = self.db_connector.query(query)
465+
status = Status.Status(self.db_connector)
466+
schema = status.get_schema()
468467

469468
try:
470-
dictio = res[0]["FindImageInfo"]["entities"]["classes"][0]["_Image"]
471-
search_key = "VD:" # TODO WHAT IS THIS?
472-
props_array = [key for key, val in dictio.items() if not search_key in key]
469+
dictio = schema["entities"]["classes"]["_Image"]["properties"]
470+
props_array = [key for key, val in dictio.items()]
473471
except:
474472
props_array = []
475473
print("Cannot retrieve properties")

aperturedb/NotebookHelpers.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
import numpy as np
44

55
from PIL import Image
6+
from IPython.display import Video
67
from IPython.display import display as ds
78

8-
DESTINATION_FOLDER = "result_images"
9+
DESTINATION_FOLDER = "results"
910

1011
def check_folder(folder):
1112
if not os.path.exists(folder):
@@ -53,3 +54,14 @@ def draw_bboxes(image, boxes=[], tags=[], save=False):
5354
check_folder(DESTINATION_FOLDER)
5455
img_file = DESTINATION_FOLDER + '/res_bboxes.jpg'
5556
cv2.imwrite(img_file, cv_image)
57+
58+
def display_video_mp4(blob):
59+
60+
check_folder(DESTINATION_FOLDER)
61+
62+
name = DESTINATION_FOLDER + "/" + "video_tmp.mp4"
63+
fd = open(name, 'wb')
64+
fd.write(blob)
65+
fd.close()
66+
67+
ds(Video(name, embed=True))

aperturedb/Status.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,27 @@ def status(self):
2323

2424
return self.connector.get_last_response_str()
2525

26+
def get_schema(self, refresh=False):
27+
28+
query = [ {
29+
"GetSchema": {
30+
"type" : "entities",
31+
"refresh": refresh,
32+
}
33+
}]
34+
35+
res, blobs = self.connector.query(query)
36+
37+
schema = {}
38+
39+
try:
40+
schema = res[0]["GetSchema"]
41+
except:
42+
print("Cannot retrieve schema")
43+
print(self.connector.get_last_response_str())
44+
45+
return schema
46+
2647
def count_images(self, constraints={}):
2748

2849
q = [{

aperturedb/VideoDownloader.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import time
2+
import requests
3+
import os
4+
from os import path
5+
6+
import cv2
7+
import numpy as np
8+
9+
from aperturedb import ParallelLoader
10+
from aperturedb import CSVParser
11+
from aperturedb import ProgressBar
12+
13+
HEADER_PATH = "filename"
14+
HEADER_URL = "url"
15+
16+
class VideoDownloaderCSV(CSVParser.CSVParser):
17+
18+
'''
19+
ApertureDB Video Downloader.
20+
Expects a csv file with AT LEAST a "url" column, and
21+
optionally a "filename" field.
22+
If "filename" is not present, it is taken from the url.
23+
'''
24+
25+
def __init__(self, filename, check_video=True):
26+
27+
self.has_filename = False
28+
self.check_video = check_video
29+
30+
super().__init__(filename)
31+
32+
def __getitem__(self, idx):
33+
34+
url = self.df.loc[idx, HEADER_URL]
35+
36+
if self.has_filename:
37+
filename = self.df.loc[idx, HEADER_PATH]
38+
else:
39+
filename = self.url_to_filename(url)
40+
41+
return url, filename
42+
43+
def url_to_filename(self, url):
44+
45+
filename = url.split("/")[-1]
46+
folder = "/tmp/videos/"
47+
48+
return folder + filename
49+
50+
def validate(self):
51+
52+
self.header = list(self.df.columns.values)
53+
54+
if HEADER_URL not in self.header:
55+
raise Exception("Error with CSV file field: url. Must be a field")
56+
57+
if HEADER_PATH in self.header:
58+
self.has_filename = True
59+
60+
class VideoDownloader(ParallelLoader.ParallelLoader):
61+
62+
def __init__(self, db, dry_run=False):
63+
64+
super().__init__(db, dry_run=dry_run)
65+
66+
self.type = "video"
67+
68+
self.check_video = False
69+
70+
def check_if_video_is_ok(self, filename, url):
71+
72+
if not os.path.exists(filename):
73+
return False
74+
75+
try:
76+
a = cv2.VideoCapture(filename)
77+
if a.isOpened() == False:
78+
print("Video present but error reading it:", url)
79+
return False
80+
except:
81+
print("Video present but error decoding:", url)
82+
return False
83+
84+
return True
85+
86+
def download_video(self, url, filename):
87+
88+
start = time.time()
89+
90+
if self.check_video and self.check_if_video_is_ok(filename, url):
91+
return
92+
93+
folder = os.path.dirname(filename)
94+
if not os.path.exists(folder):
95+
os.makedirs(folder, exist_ok=True)
96+
97+
videodata = requests.get(url)
98+
if videodata.ok:
99+
fd = open(filename, "wb")
100+
fd.write(videodata.content)
101+
fd.close()
102+
103+
try:
104+
a = cv2.VideoCapture(filename)
105+
if a.isOpened() == False:
106+
print("Downloaded Video size error:", url)
107+
os.remove(filename)
108+
self.error_counter += 1
109+
except:
110+
print("Downloaded Video cannot be decoded:", url)
111+
os.remove(filename)
112+
self.error_counter += 1
113+
else:
114+
print("URL not found:", url)
115+
self.error_counter += 1
116+
117+
self.times_arr.append(time.time() - start)
118+
119+
def worker(self, thid, generator, start, end):
120+
121+
if thid == 0 and self.stats:
122+
pb = ProgressBar.ProgressBar("download_progress.txt")
123+
124+
for i in range(start, end):
125+
126+
url, filename = generator[i]
127+
128+
self.download_video(url, filename)
129+
130+
if thid == 0 and self.stats:
131+
pb.update((i - start) / (end - start))
132+
133+
if thid == 0 and self.stats:
134+
pb.update(1)
135+
136+
def print_stats(self):
137+
138+
print("====== ApertureDB VideoDownloader Stats ======")
139+
140+
times = np.array(self.times_arr)
141+
print("Avg Video download time(s):", np.mean(times))
142+
print("Img download time std:", np.std (times))
143+
print("Avg download throughput (videos/s)):",
144+
1 / np.mean(times) * self.numthreads)
145+
146+
print("Total time(s):", self.ingestion_time)
147+
print("Overall throughput (videos/s):",
148+
self.total_elements / self.ingestion_time)
149+
print("Total errors encountered:", self.error_counter)
150+
print("=============================================")

0 commit comments

Comments
 (0)