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