fixed layer.add()
This commit is contained in:
parent
01b5d7f9a9
commit
3c3c8da9cd
|
|
@ -3,25 +3,27 @@ class Config:
|
||||||
c = {
|
c = {
|
||||||
"min_area" : 100,
|
"min_area" : 100,
|
||||||
"max_area" : 40000,
|
"max_area" : 40000,
|
||||||
"threashold" : 5,
|
"threashold" : 8,
|
||||||
"resizeWidth" : 512,
|
"resizeWidth" : 512,
|
||||||
"inputPath" : None,
|
"inputPath" : None,
|
||||||
"outputPath": None,
|
"outputPath": None,
|
||||||
"maxLayerLength": 900,
|
"maxLayerLength": 900,
|
||||||
"minLayerLength": 20,
|
"minLayerLength": 20,
|
||||||
"tolerance": 20,
|
"tolerance": 10,
|
||||||
"maxLength": None,
|
"maxLength": None,
|
||||||
"ttolerance": 60,
|
"ttolerance": 60,
|
||||||
"videoBufferLength": 500,
|
"videoBufferLength": 500,
|
||||||
"noiseThreashold": 0.3,
|
"noiseThreashold": 0.25,
|
||||||
"noiseSensitivity": 3/4,
|
"noiseSensitivity": 3/4,
|
||||||
"LayersPerContour": 5,
|
"LayersPerContour": 2,
|
||||||
"averageFrames": 10
|
"avgNum":10
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
'''This is basically just a wrapper for a json / python dict'''
|
'''This is basically just a wrapper for a json / python dict'''
|
||||||
print("Current Config:", self.c)
|
print("Current Config:")
|
||||||
|
for key, value in self.c.items():
|
||||||
|
print(f"{key}:\t\t{value}")
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if key not in self.c:
|
if key not in self.c:
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,9 @@ class ContourExtractor:
|
||||||
|
|
||||||
def computeMovingAverage(self, frames):
|
def computeMovingAverage(self, frames):
|
||||||
avg = []
|
avg = []
|
||||||
averageFrames = self.config["averageFrames"]
|
averageFrames = self.config["avgNum"]
|
||||||
|
|
||||||
|
nth = int(averageFrames/3) # only take /x x frames to average
|
||||||
if frames[0][0] < averageFrames:
|
if frames[0][0] < averageFrames:
|
||||||
frame = frames[0][1]
|
frame = frames[0][1]
|
||||||
frame = self.prepareFrame(frame)
|
frame = self.prepareFrame(frame)
|
||||||
|
|
@ -123,7 +125,7 @@ class ContourExtractor:
|
||||||
if self.lastFrames is not None:
|
if self.lastFrames is not None:
|
||||||
frames = self.lastFrames + frames
|
frames = self.lastFrames + frames
|
||||||
|
|
||||||
tmp = [[j, frames, averageFrames]for j in range(averageFrames, len(frames))]
|
tmp = [[j, frames, averageFrames] for j in range(averageFrames, len(frames))]
|
||||||
with ThreadPool(16) as pool:
|
with ThreadPool(16) as pool:
|
||||||
pool.map(self.averageDaFrames, tmp)
|
pool.map(self.averageDaFrames, tmp)
|
||||||
|
|
||||||
|
|
@ -136,6 +138,6 @@ class ContourExtractor:
|
||||||
frame = self.prepareFrame(frame)
|
frame = self.prepareFrame(frame)
|
||||||
|
|
||||||
avg = frame/averageFrames
|
avg = frame/averageFrames
|
||||||
for jj in reversed(range(averageFrames-1)):
|
for jj in range(0,averageFrames-1):
|
||||||
avg += self.prepareFrame(frames[j-jj][1])/averageFrames
|
avg += self.prepareFrame(frames[j-jj][1])/averageFrames
|
||||||
self.averages[frameNumber] = np.array(np.round(avg), dtype=np.uint8)
|
self.averages[frameNumber] = np.array(np.round(avg), dtype=np.uint8)
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,13 @@ class Exporter:
|
||||||
self.config = config
|
self.config = config
|
||||||
print("Exporter initiated")
|
print("Exporter initiated")
|
||||||
|
|
||||||
def export(self, layers, raw = True, layered = False, overlayed = True):
|
def export(self, layers, contours, raw = True, overlayed = True):
|
||||||
|
|
||||||
if raw:
|
if raw:
|
||||||
self.exportRawData(layers)
|
self.exportRawData(layers, contours)
|
||||||
if layered and overlayed:
|
if overlayed:
|
||||||
print("Layered and Individual are mutually exclusive, individual was choosen automatically")
|
|
||||||
overlayed = False
|
|
||||||
if layered and not overlayed:
|
|
||||||
self.exportLayers(layers)
|
|
||||||
if overlayed and not layered:
|
|
||||||
self.exportOverlayed(layers)
|
self.exportOverlayed(layers)
|
||||||
|
else:
|
||||||
|
self.exportLayers(layers)
|
||||||
|
|
||||||
|
|
||||||
def exportLayers(self, layers):
|
def exportLayers(self, layers):
|
||||||
|
|
@ -37,7 +33,6 @@ class Exporter:
|
||||||
maxLength = self.getMaxLengthOfLayers(layers)
|
maxLength = self.getMaxLengthOfLayers(layers)
|
||||||
underlay = cv2.VideoCapture(self.footagePath).read()[1]
|
underlay = cv2.VideoCapture(self.footagePath).read()[1]
|
||||||
underlay = cv2.cvtColor(underlay, cv2.COLOR_BGR2RGB)
|
underlay = cv2.cvtColor(underlay, cv2.COLOR_BGR2RGB)
|
||||||
frames = [underlay]*maxLength
|
|
||||||
exportFrame = 0
|
exportFrame = 0
|
||||||
|
|
||||||
self.fps = videoReader.getFPS()
|
self.fps = videoReader.getFPS()
|
||||||
|
|
@ -52,7 +47,7 @@ class Exporter:
|
||||||
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||||
|
|
||||||
frame2 = np.copy(underlay)
|
frame2 = np.copy(underlay)
|
||||||
for layer in layers:
|
for xi, layer in enumerate(layers):
|
||||||
if layer.startFrame <= frameCount and layer.startFrame + len(layer.bounds) > frameCount:
|
if layer.startFrame <= frameCount and layer.startFrame + len(layer.bounds) > frameCount:
|
||||||
for (x, y, w, h) in layer.bounds[frameCount - layer.startFrame]:
|
for (x, y, w, h) in layer.bounds[frameCount - layer.startFrame]:
|
||||||
if x is None:
|
if x is None:
|
||||||
|
|
@ -64,7 +59,7 @@ class Exporter:
|
||||||
h = int(h * factor)
|
h = int(h * factor)
|
||||||
|
|
||||||
frame2[y:y+h, x:x+w] = np.copy(frame[y:y+h, x:x+w])
|
frame2[y:y+h, x:x+w] = np.copy(frame[y:y+h, x:x+w])
|
||||||
cv2.putText(frame2, str(int(frameCount/self.fps)), (int(x+w/2), int(y+h/2)), cv2.FONT_HERSHEY_SIMPLEX, 1,(255,255,255), 2)
|
cv2.putText(frame2, str(xi) + " " + str(int(frameCount/self.fps)), (int(x+w/2), int(y+h/2)), cv2.FONT_HERSHEY_SIMPLEX, 1,(255,255,255), 2)
|
||||||
writer.append_data(frame2)
|
writer.append_data(frame2)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -119,9 +114,10 @@ class Exporter:
|
||||||
|
|
||||||
writer.close()
|
writer.close()
|
||||||
|
|
||||||
def exportRawData(self, layers):
|
def exportRawData(self, layers, contours):
|
||||||
with open(self.outputPath.split(".")[-2] + ".txt", "wb+") as file:
|
with open(self.config["importPath"], "wb+") as file:
|
||||||
pickle.dump(layers, file)
|
pickle.dump((layers, contours), file)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def getMaxLengthOfLayers(self, layers):
|
def getMaxLengthOfLayers(self, layers):
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ class Importer:
|
||||||
self.path = config["importPath"]
|
self.path = config["importPath"]
|
||||||
|
|
||||||
def importRawData(self):
|
def importRawData(self):
|
||||||
|
print("Loading previous results")
|
||||||
with open(self.path, "rb") as file:
|
with open(self.path, "rb") as file:
|
||||||
layers = pickle.load(file)
|
layers, contours = pickle.load(file)
|
||||||
return layers
|
return (layers, contours)
|
||||||
|
|
@ -37,15 +37,13 @@ class Layer:
|
||||||
|
|
||||||
def add(self, frameNumber, bound):
|
def add(self, frameNumber, bound):
|
||||||
'''Adds a bound'''
|
'''Adds a bound'''
|
||||||
if not self.startFrame + len(self.bounds) < frameNumber:
|
if self.startFrame + len(self.bounds) - 1 > frameNumber:
|
||||||
if len(self.bounds[self.startFrame - frameNumber]) >= 1:
|
if len(self.bounds[frameNumber - self.startFrame]) >= 1:
|
||||||
self.bounds[self.startFrame - frameNumber].append(bound)
|
self.bounds[frameNumber - self.startFrame].append(bound)
|
||||||
else:
|
else:
|
||||||
self.lastFrame = frameNumber
|
self.lastFrame = frameNumber
|
||||||
self.bounds.append([bound])
|
self.bounds.append([bound])
|
||||||
|
|
||||||
self.getLength()
|
|
||||||
|
|
||||||
def getLength(self):
|
def getLength(self):
|
||||||
return len(self)
|
return len(self)
|
||||||
|
|
||||||
|
|
@ -53,25 +51,6 @@ class Layer:
|
||||||
self.length = len(self.bounds)
|
self.length = len(self.bounds)
|
||||||
return self.length
|
return self.length
|
||||||
|
|
||||||
def fill(self, inputPath, resizeWidth):
|
|
||||||
'''deprecated
|
|
||||||
|
|
||||||
Fills the data[] array by iterateing over the bounds'''
|
|
||||||
|
|
||||||
cap = cv2.VideoCapture(inputPath)
|
|
||||||
self.data = [None]*len(self.bounds)
|
|
||||||
i = 0
|
|
||||||
cap.set(1, self.startFrame)
|
|
||||||
while i < len(self.bounds):
|
|
||||||
ret, frame = cap.read()
|
|
||||||
|
|
||||||
if ret:
|
|
||||||
frame = imutils.resize(frame, width=resizeWidth)
|
|
||||||
(x, y, w, h) = self.bounds[i]
|
|
||||||
self.data[i] = frame[y:y+h, x:x+w]
|
|
||||||
i+=1
|
|
||||||
cap.release()
|
|
||||||
|
|
||||||
def clusterDelete(self):
|
def clusterDelete(self):
|
||||||
'''Uses a cluster analysis to remove contours which are not the result of movement'''
|
'''Uses a cluster analysis to remove contours which are not the result of movement'''
|
||||||
org = self.bounds
|
org = self.bounds
|
||||||
|
|
@ -146,13 +125,14 @@ class Layer:
|
||||||
newContours = [[]]
|
newContours = [[]]
|
||||||
for i, dis in enumerate(dists):
|
for i, dis in enumerate(dists):
|
||||||
# copy contours which are spread out, delete rest by not copying them
|
# copy contours which are spread out, delete rest by not copying them
|
||||||
if dis > noiseThreashold:
|
|
||||||
for j in classed[i]:
|
for j in classed[i]:
|
||||||
x, y = mapping[j]
|
x, y = mapping[j]
|
||||||
while x >= len(newContours):
|
while x >= len(newContours):
|
||||||
newContours.append([])
|
newContours.append([])
|
||||||
while y > len(newContours[x]):
|
while y > len(newContours[x]):
|
||||||
newContours[x].append((None, None, None, None))
|
newContours[x].append((None, None, None, None))
|
||||||
|
if dis > noiseThreashold:
|
||||||
newContours[x].append(org[x][y])
|
newContours[x].append(org[x][y])
|
||||||
|
|
||||||
self.bounds = newContours
|
self.bounds = newContours
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,9 @@ class LayerFactory:
|
||||||
print(f"{int(round(frameNumber/max(data.keys()), 2)*100)}% done with Layer extraction")
|
print(f"{int(round(frameNumber/max(data.keys()), 2)*100)}% done with Layer extraction")
|
||||||
|
|
||||||
tmp = [[frameNumber, contour] for contour in contours]
|
tmp = [[frameNumber, contour] for contour in contours]
|
||||||
pool.map(self.getLayers, tmp)
|
#pool.map(self.getLayers, tmp)
|
||||||
#for x in tmp:
|
for x in tmp:
|
||||||
#self.getLayers(x)
|
self.getLayers(x)
|
||||||
|
|
||||||
return self.layers
|
return self.layers
|
||||||
|
|
||||||
|
|
@ -59,20 +59,28 @@ class LayerFactory:
|
||||||
foundLayer = 0
|
foundLayer = 0
|
||||||
|
|
||||||
for i in range(0, len(self.layers)):
|
for i in range(0, len(self.layers)):
|
||||||
|
if foundLayer >= self.config["LayersPerContour"]:
|
||||||
|
break
|
||||||
|
|
||||||
if i in self.oldLayerIDs:
|
if i in self.oldLayerIDs:
|
||||||
continue
|
continue
|
||||||
if frameNumber - self.layers[i].lastFrame > self.ttolerance:
|
if frameNumber - self.layers[i].lastFrame > self.ttolerance:
|
||||||
self.oldLayerIDs.append(i)
|
self.oldLayerIDs.append(i)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for bounds in self.layers[i].bounds[-1]:
|
lastXframes = 3
|
||||||
if bounds is None or foundLayer >= self.config["LayersPerContour"]:
|
if len(self.layers[i].bounds) < lastXframes:
|
||||||
|
lastXframes = len(self.layers[i].bounds)
|
||||||
|
lastBounds = [bound for bounds in self.layers[i].bounds[-lastXframes:] for bound in bounds]
|
||||||
|
|
||||||
|
for bounds in lastBounds:
|
||||||
|
if bounds is None:
|
||||||
break
|
break
|
||||||
(x2,y2,w2,h2) = bounds
|
(x2,y2,w2,h2) = bounds
|
||||||
if self.contoursOverlay((x-tol,y+h+tol), (x+w+tol,y-tol), (x2,y2+h2), (x2+w2,y2)):
|
if self.contoursOverlay((x-tol,y+h+tol), (x+w+tol,y-tol), (x2,y2+h2), (x2+w2,y2)):
|
||||||
self.layers[i].add(frameNumber, (x,y,w,h))
|
self.layers[i].add(frameNumber, (x,y,w,h))
|
||||||
foundLayer += 1
|
foundLayer += 1
|
||||||
#break
|
break
|
||||||
|
|
||||||
if foundLayer == 0:
|
if foundLayer == 0:
|
||||||
self.layers.append(Layer(frameNumber, (x,y,w,h), self.config))
|
self.layers.append(Layer(frameNumber, (x,y,w,h), self.config))
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class LayerManager:
|
||||||
print("'Cleaning' Layers")
|
print("'Cleaning' Layers")
|
||||||
self.freeMin()
|
self.freeMin()
|
||||||
self.sortLayers()
|
self.sortLayers()
|
||||||
self.cleanLayers2()
|
#self.cleanLayers2()
|
||||||
self.freeMax()
|
self.freeMax()
|
||||||
|
|
||||||
def removeStaticLayers(self):
|
def removeStaticLayers(self):
|
||||||
|
|
@ -107,5 +107,8 @@ class LayerManager:
|
||||||
self.layers.sort(key = lambda c:c.startFrame)
|
self.layers.sort(key = lambda c:c.startFrame)
|
||||||
|
|
||||||
def cleanLayers2(self):
|
def cleanLayers2(self):
|
||||||
|
#with ThreadPool(16) as pool:
|
||||||
|
# pool.map(self.getContours, tmpData)
|
||||||
|
|
||||||
for layer in self.layers:
|
for layer in self.layers:
|
||||||
layer.clusterDelete()
|
layer.clusterDelete()
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import cv2
|
import cv2
|
||||||
import imageio
|
import imageio
|
||||||
import time
|
import time
|
||||||
writer = imageio.get_writer("./x23.mp4", fps=20)
|
writer = imageio.get_writer("./x23.mp4", fps=15)
|
||||||
|
|
||||||
url = "http://50.227.41.1/mjpg/video.mjpg"
|
url = "http://50.227.41.1/mjpg/video.mjpg"
|
||||||
i = 0
|
i = 0
|
||||||
|
|
@ -20,15 +20,15 @@ while True :
|
||||||
print("Error in cap.read()") # this is for preventing a breaking error
|
print("Error in cap.read()") # this is for preventing a breaking error
|
||||||
# break;
|
# break;
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
continue
|
break
|
||||||
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||||
writer.append_data(frame)
|
writer.append_data(frame)
|
||||||
i+=1
|
i+=1
|
||||||
|
|
||||||
if i > 20*60*60:
|
if i > 20*60*60*2:
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
print("meh")
|
||||||
cap.release()
|
cap.release()
|
||||||
cv2.destroyAllWindows()
|
cv2.destroyAllWindows()
|
||||||
writer.close()
|
writer.close()
|
||||||
25
main.py
25
main.py
|
|
@ -14,22 +14,26 @@ def main():
|
||||||
start = time.time()
|
start = time.time()
|
||||||
config = Config()
|
config = Config()
|
||||||
|
|
||||||
config["inputPath"] = os.path.join(os.path.dirname(__file__), "generate test footage/Merica-1.m4v")
|
fileName = "3.mp4"
|
||||||
#config["importPath"] = os.path.join(os.path.dirname(__file__), "output/short.txt")
|
outputPath = os.path.join(os.path.dirname(__file__), "output")
|
||||||
config["outputPath"] = os.path.join(os.path.dirname(__file__), "output/shor.mp4")
|
dirName = os.path.join(os.path.dirname(__file__), "generate test footage")
|
||||||
|
|
||||||
vr = VideoReader(config)
|
config["inputPath"] = os.path.join(dirName, fileName)
|
||||||
config["w"], config["h"] = vr.getWH()
|
config["outputPath"] = os.path.join(outputPath, fileName)
|
||||||
|
|
||||||
if config["importPath"] is None:
|
config["importPath"] = os.path.join(outputPath, fileName.split(".")[0] + ".txt")
|
||||||
|
|
||||||
|
config["w"], config["h"] = VideoReader(config).getWH()
|
||||||
|
|
||||||
|
if not os.path.exists(config["importPath"]):
|
||||||
contours = ContourExtractor(config).extractContours()
|
contours = ContourExtractor(config).extractContours()
|
||||||
print("Time consumed extracting: ", time.time() - start)
|
print("Time consumed extracting: ", time.time() - start)
|
||||||
layerFactory = LayerFactory(config)
|
layerFactory = LayerFactory(config)
|
||||||
|
|
||||||
layers = layerFactory.extractLayers(contours)
|
layers = layerFactory.extractLayers(contours)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
layers = Importer(config).importRawData()
|
layers, contours = Importer(config).importRawData()
|
||||||
|
#layerFactory = LayerFactory(config)
|
||||||
|
#layers = layerFactory.extractLayers(contours)
|
||||||
|
|
||||||
layerManager = LayerManager(config, layers)
|
layerManager = LayerManager(config, layers)
|
||||||
layerManager.cleanLayers()
|
layerManager.cleanLayers()
|
||||||
|
|
@ -37,7 +41,8 @@ def main():
|
||||||
#layerManager.tagLayers()
|
#layerManager.tagLayers()
|
||||||
layers = layerManager.layers
|
layers = layerManager.layers
|
||||||
exporter = Exporter(config)
|
exporter = Exporter(config)
|
||||||
exporter.export(layers, raw=False)
|
print(f"Exporting {len(contours)} Contours and {len(layers)} Layers")
|
||||||
|
exporter.export(layers, contours, raw=True, overlayed=False)
|
||||||
|
|
||||||
print("Total time: ", time.time() - start)
|
print("Total time: ", time.time() - start)
|
||||||
|
|
||||||
|
|
|
||||||
BIN
output/3.txt
BIN
output/3.txt
Binary file not shown.
Binary file not shown.
BIN
output/short.txt
BIN
output/short.txt
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 311 KiB After Width: | Height: | Size: 313 KiB |
Loading…
Reference in New Issue