This commit is contained in:
Askill 2020-12-22 13:58:47 +01:00
parent c828e2e0d2
commit 529459aa97
9 changed files with 45 additions and 63 deletions

View File

@ -1,7 +1,7 @@
class Config:
c = {
"min_area" : 5000,
"min_area" : 50,
"max_area" : 40000,
"threashold" : 7,
"resizeWidth" : 512,
@ -11,7 +11,7 @@ class Config:
"minLayerLength": 40,
"tolerance": 20,
"maxLength": None,
"ttolerance": 20,
"ttolerance": 60,
"videoBufferLength": 500,
"LayersPerContour": 220,
"avgNum":10

View File

@ -50,26 +50,32 @@ class ContourExtractor:
def extractContours(self):
videoReader = VideoReader(self.config)
self.fps = videoReader.getFPS()
self.length = videoReader.getLength()
videoReader.fillBuffer()
threads = self.config["videoBufferLength"]
self.start = time.time()
# start a bunch of frames and let them read from the video reader buffer until the video reader reaches EOF
with ThreadPool(16) as pool:
with ThreadPool(2) as pool:
while not videoReader.videoEnded():
if videoReader.buffer.qsize() == 0:
time.sleep(.5)
tmpData = [videoReader.pop() for i in range(0, videoReader.buffer.qsize())]
self.computeMovingAverage(tmpData)
pool.map_async(self.getContours, tmpData)
pool.map(self.computeMovingAverage, (tmpData,))
pool.map(self.async2, (tmpData,))
#for data in tmpData:
# self.getContours(data)
frameCount = tmpData[-1][0]
videoReader.thread.join()
return self.extractedContours, self.extractedMasks
def async2(self, tmpData):
with ThreadPool(16) as pool2:
pool2.map(self.getContours, tmpData)
def getContours(self, data):
frameCount, frame = data
# wait for the reference frame, which is calculated by averaging some revious frames
@ -77,8 +83,8 @@ class ContourExtractor:
time.sleep(0.1)
firstFrame = self.averages.pop(frameCount, None)
if frameCount % (60*30) == 1:
print(f" \r {frameCount/(60*30)} Minutes processed in {round((time.time() - self.start)/(frameCount/(60*30)), 2)} each", end='\r')
if frameCount % (10*self.fps) == 1:
print(f" \r {round((frameCount/self.fps)/self.length, 4)*100} % processed in {round(time.time() - self.start, 2)}s", end='\r')
gray = self.prepareFrame(frame)
frameDelta = cv2.absdiff(gray, firstFrame)
@ -88,7 +94,6 @@ class ContourExtractor:
#cv2.imshow("changes x", thresh)
#cv2.waitKey(10) & 0XFF
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
self.diff.append(np.count_nonzero(thresh))
cnts = imutils.grab_contours(cnts)
contours = []

View File

@ -28,6 +28,7 @@ class VideoReader:
self.stopped = False
self.getWH()
self.calcFPS()
self.calcLength()
self.calcStartTime()
if setOfFrames is not None:
self.listOfFrames = sorted(setOfFrames)
@ -103,12 +104,22 @@ class VideoReader:
self.fps = self.vc.get(cv2.CAP_PROP_FPS)
def getFPS(self):
if self.fps is None:
self.calcFPS()
return self.fps
def calcLength(self):
fc = int(self.vc.get(cv2.CAP_PROP_FRAME_COUNT))
self.length = fc / self.getFPS()
def getLength(self):
if self.length is None:
self.calcLength()
return self.length
def calcStartTime(self):
starttime = os.stat(self.videoPath).st_mtime
fc = int(self.vc.get(cv2.CAP_PROP_FRAME_COUNT))
length = fc / self.getFPS()
length = self.getLength()
starttime = starttime - length
self.starttime = starttime

View File

@ -1,12 +1,18 @@
# wip
# Video Synopsis and Classification
## Example:
![docs/demo.gif](./docs/demo.gif)
What you see above is a 15 second exerpt of a 2 minute overlayed synopsis of a 2.5h video from an on campus web cam.
The synopsis took 40 minutes from start to finish on a 8 core machine and used a maximum of 6Gb of RAM.
## Benchmark
Below you can find the benchmark results for a 10 minutes clip, with the stacked time per componenent on the x-axis.
The tests were done on a machine with a Ryzen 3700X with 8 cores 16 threads and 32 Gb of RAM.
![docs/demo.gif](./docs/bm.jpg)
#### notes:
Time consumed reading video: 369.0188868045807s 3.06GB 26min 1080p downscaled 500p 30fps
Time consumed reading video: 240.s 3.06GB 26min 1080p downscaled 500p 30fps when multithreaded
contour extraction: 10.5 Sec. when only 2 Threads
8 secs when also mapping getContours()
install tensorflow==1.15.0 and tensorflow-gpu==1.15.0, cuda 10.2 and 10.0, copy missing files from 10.0 to 10.2, restart computer, set maximum vram

BIN
docs/bm.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
docs/demo.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 MiB

View File

@ -1,22 +0,0 @@
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
[
{"threads": "32, 16", "Contour Extractor": 106.0405707359314, "Layer Factory": 0.5175004005432129, "Layer Manager": 1.4864997863769531, "Exporter": 34.591999769210815},
{"threads": "1, 1", "Contour Extractor": 463.66750025749207, "Layer Factory": 0.5290005207061768, "Layer Manager": 1.551999807357788, "Exporter": 34.5339994430542},
{"threads": "1, 4", "Contour Extractor": 193.51898574829102, "Layer Factory": 0.5249984264373779, "Layer Manager": 1.5125021934509277, "Exporter": 35.06749963760376},
{"threads": "4, 4", "Contour Extractor": 186.46951842308044, "Layer Factory": 0.5295009613037109, "Layer Manager": 1.545145034790039, "Exporter": 34.260000705718994},
{"threads": "4, 8", "Contour Extractor": 126.90402793884277, "Layer Factory": 0.5275006294250488, "Layer Manager": 1.536078929901123, "Exporter": 34.61099886894226},
{"threads": "16, 16", "Contour Extractor": 109.17592716217041, "Layer Factory": 0.4179983139038086, "Layer Manager": 1.5620002746582031, "Exporter": 33.80550146102905},
]
x = {
"threads":["1, 1","1, 4","4, 4","4, 8","16, 16", "32, 16"],
"Contour Extraction":[ 463.66750025749207, 193.51898574829102,186.46951842308044,126.90402793884277,109.17592716217041,106.0405707359314],
}
df = pd.DataFrame.from_dict(x)
ax = df.plot.bar(x="threads", title="Benötigte Zeit für Konturenextraktion mit unterschiedlicher Anzahlen von Threads", figsize=(10,4))
ax.set_xlabel("Threads für Durchschnittsbildung | Threads für Differenzberechnung")
ax.set_ylabel("Zeit in Sekunden")
plt.show()

View File

@ -1,9 +0,0 @@
[
{"File Name": "c:/projects/time compression\\output\\X23-1.txt", "threads": "32, 16", "Contour Extractor": 106.0405707359314, "Layer Factory": 0.5175004005432129, "Layer Manager": 1.4864997863769531, "Exporter": 34.591999769210815},
{"File Name": "c:/projects/time compression\\output\\X23-1.txt", "threads": "1, 1", "Contour Extractor": 463.66750025749207, "Layer Factory": 0.5290005207061768, "Layer Manager": 1.551999807357788, "Exporter": 34.5339994430542},
{"File Name": "c:/projects/time compression\\output\\X23-1.txt", "threads": "1, 4", "Contour Extractor": 193.51898574829102, "Layer Factory": 0.5249984264373779, "Layer Manager": 1.5125021934509277, "Exporter": 35.06749963760376},
{"File Name": "c:/projects/time compression\\output\\X23-1.txt", "threads": "4, 4", "Contour Extractor": 186.46951842308044, "Layer Factory": 0.5295009613037109, "Layer Manager": 1.545145034790039, "Exporter": 34.260000705718994},
{"File Name": "c:/projects/time compression\\output\\X23-1.txt", "threads": "4, 8", "Contour Extractor": 126.90402793884277, "Layer Factory": 0.5275006294250488, "Layer Manager": 1.536078929901123, "Exporter": 34.61099886894226},
{"File Name": "c:/projects/time compression\\output\\X23-1.txt", "threads": "16, 16", "Contour Extractor": 109.17592716217041, "Layer Factory": 0.4179983139038086, "Layer Manager": 1.5620002746582031, "Exporter": 33.80550146102905},
]

19
main.py
View File

@ -15,7 +15,7 @@ def main():
start = startTotal
config = Config()
fileName = "3.mp4"
fileName = "x23.mp4"
outputPath = os.path.join(os.path.dirname(__file__), "output")
dirName = os.path.join(os.path.dirname(__file__), "generate test footage")
@ -25,26 +25,20 @@ def main():
config["importPath"] = os.path.join(outputPath, fileName.split(".")[0] + ".txt")
config["w"], config["h"] = VideoReader(config).getWH()
stats = []
if not os.path.exists(config["importPath"]):
contours, masks = ContourExtractor(config).extractContours()
stats.append(time.time() - start)
start = time.time()
print("Time consumed extracting contours: ", stats["Contour Extractor"])
layerFactory = LayerFactory(config)
layers = layerFactory.extractLayers(contours, masks)
stats.append(time.time() - start)
start = time.time()
else:
layers, contours, masks = Importer(config).importRawData()
#layerFactory = LayerFactory(config)
#layers = layerFactory.extractLayers(contours, masks)
layerFactory = LayerFactory(config)
layers = layerFactory.extractLayers(contours, masks)
layerManager = LayerManager(config, layers)
layerManager.transformLayers()
stats.append(time.time() - start)
start = time.time()
#layerManager.tagLayers()
layers = layerManager.layers
@ -54,11 +48,8 @@ def main():
exporter = Exporter(config)
print(f"Exporting {len(contours)} Contours and {len(layers)} Layers")
exporter.export(layers, contours, masks, raw=True, overlayed=True)
stats.append(time.time() - start)
print("Total time: ", time.time() - startTotal)
stats.append(time.time() - startTotal)
print(stats)
exit(0)
if __name__ == "__main__":