- improved PiCameraPipeline (added names for procs, better thread mgmt)
- added VideoSource to piCameraPipeline git-svn-id: http://moon:8086/svn/software/trunk/projects/opencv@330 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
+5
-48
@@ -21,6 +21,7 @@ from picamera import PiCamera
|
|||||||
from piCameraPipeline import PiCameraPipeline
|
from piCameraPipeline import PiCameraPipeline
|
||||||
from piCameraPipeline.PiCameraPipeline import RgbProcess
|
from piCameraPipeline.PiCameraPipeline import RgbProcess
|
||||||
from piCameraPipeline.PiCameraPipeline import RgbProcessorAdapter
|
from piCameraPipeline.PiCameraPipeline import RgbProcessorAdapter
|
||||||
|
from piCameraPipeline.VideoSource import VideoSource
|
||||||
|
|
||||||
width = 320
|
width = 320
|
||||||
height = 240
|
height = 240
|
||||||
@@ -42,52 +43,9 @@ framerate = args["framerate"]
|
|||||||
seconds = args["seconds"]
|
seconds = args["seconds"]
|
||||||
with_ev3 = args["with_ev3"]
|
with_ev3 = args["with_ev3"]
|
||||||
|
|
||||||
class VideoSource(RgbProcessorAdapter):
|
|
||||||
def __init__(self, fileName, resolution, framerate):
|
|
||||||
super(VideoSource, self).__init__(resolution)
|
|
||||||
self.fileName = fileName
|
|
||||||
self.resolution = resolution
|
|
||||||
self.framerate = framerate
|
|
||||||
self.thread = None
|
|
||||||
self.camera = None
|
|
||||||
self.cancel = False
|
|
||||||
if fileName == 'piCamera':
|
|
||||||
self.camera = PiCamera()
|
|
||||||
self.camera.resolution = (self.resolution[0], self.resolution[1])
|
|
||||||
self.camera.framerate = self.framerate
|
|
||||||
else:
|
|
||||||
self.needRgbConversion = False
|
|
||||||
self.thread = Thread(target=self.fileReadThread)
|
|
||||||
|
|
||||||
def fileReadThread(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
if self.thread is not None:
|
|
||||||
self.thread.start()
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.camera.start_recording(self, format="bgr")
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
if self.thread is not None:
|
|
||||||
self.cancel = True
|
|
||||||
self.thread.join()
|
|
||||||
else:
|
|
||||||
self.camera.stop_recording()
|
|
||||||
|
|
||||||
def fileReadThread(self):
|
|
||||||
cap = cv2.VideoCapture(self.fileName)
|
|
||||||
while not self.cancel:
|
|
||||||
ret, frame = cap.read()
|
|
||||||
if ret:
|
|
||||||
self.write(frame)
|
|
||||||
time.sleep(1.0/self.framerate)
|
|
||||||
|
|
||||||
|
|
||||||
class MyRgbProcess(RgbProcess):
|
class MyRgbProcess(RgbProcess):
|
||||||
def __init__(self, brick, resolution=(320, 240, 3), numEntries=2, next=None):
|
def __init__(self, name, resolution=(320, 240, 3), numEntries=2, next=None, brick=None):
|
||||||
super(MyRgbProcess, self).__init__(resolution, numEntries, next)
|
super(MyRgbProcess, self).__init__(name, resolution, numEntries, next)
|
||||||
self.brick = brick
|
self.brick = brick
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
@@ -145,7 +103,7 @@ if with_ev3:
|
|||||||
with ev3.EV3() as brick:
|
with ev3.EV3() as brick:
|
||||||
|
|
||||||
videoSource = VideoSource(videoFile, (width,height,3), framerate)
|
videoSource = VideoSource(videoFile, (width,height,3), framerate)
|
||||||
proc = MyRgbProcess(brick, (240, 320, 3), 4)
|
proc = MyRgbProcess('MyRgbProcess', (240, 320, 3), 4, brick)
|
||||||
videoSource.processorAdd(proc)
|
videoSource.processorAdd(proc)
|
||||||
videoSource.start()
|
videoSource.start()
|
||||||
|
|
||||||
@@ -155,14 +113,13 @@ if with_ev3:
|
|||||||
proc.stop()
|
proc.stop()
|
||||||
else:
|
else:
|
||||||
videoSource = VideoSource(videoFile, (width,height,3), framerate)
|
videoSource = VideoSource(videoFile, (width,height,3), framerate)
|
||||||
proc = MyRgbProcess(None, (240, 320, 3), 4)
|
proc = MyRgbProcess('MyRgbProcess', (240, 320, 3), 4)
|
||||||
videoSource.processorAdd(proc)
|
videoSource.processorAdd(proc)
|
||||||
videoSource.start()
|
videoSource.start()
|
||||||
|
|
||||||
print("[INFO] sampling THREADED frames from `" + videoFile + "` at " + str(framerate) + " frame/s")
|
print("[INFO] sampling THREADED frames from `" + videoFile + "` at " + str(framerate) + " frame/s")
|
||||||
time.sleep(seconds)
|
time.sleep(seconds)
|
||||||
videoSource.stop()
|
videoSource.stop()
|
||||||
proc.stop()
|
|
||||||
|
|
||||||
# do a bit of cleanup
|
# do a bit of cleanup
|
||||||
cv2.destroyAllWindows()
|
cv2.destroyAllWindows()
|
||||||
|
|||||||
@@ -60,8 +60,9 @@ class Fifo(object):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
class RgbProcess(Fifo):
|
class RgbProcess(Fifo):
|
||||||
def __init__(self, resolution=(320, 240, 3), numEntries=2, next=None):
|
def __init__(self, name='RgbProcess', resolution=(320, 240, 3), numEntries=2, next=None):
|
||||||
super(RgbProcess, self).__init__((numEntries, ) + resolution)
|
super(RgbProcess, self).__init__((numEntries, ) + resolution)
|
||||||
|
self.name = name
|
||||||
self.next = next
|
self.next = next
|
||||||
self.thread = Thread(target=self.run)
|
self.thread = Thread(target=self.run)
|
||||||
self.cancel = False
|
self.cancel = False
|
||||||
@@ -74,9 +75,10 @@ class RgbProcess(Fifo):
|
|||||||
|
|
||||||
# called on first frame
|
# called on first frame
|
||||||
def onFirstFrame(self):
|
def onFirstFrame(self):
|
||||||
self.thread.start()
|
self.start()
|
||||||
if self.next is not None:
|
|
||||||
self.next.onFirstFrame()
|
def onLastFrame(self):
|
||||||
|
self.stop()
|
||||||
|
|
||||||
# may be overriden to process in caller context
|
# may be overriden to process in caller context
|
||||||
def onData(self, data):
|
def onData(self, data):
|
||||||
@@ -84,31 +86,46 @@ class RgbProcess(Fifo):
|
|||||||
|
|
||||||
# thread main loop
|
# thread main loop
|
||||||
def run(self):
|
def run(self):
|
||||||
self.fps = FPS().start()
|
self.started()
|
||||||
while not self.cancel:
|
while not self.cancel:
|
||||||
self.process()
|
self.process()
|
||||||
self.frames += 1
|
self.frames += 1
|
||||||
|
|
||||||
|
self.stopped()
|
||||||
|
|
||||||
|
def started(self):
|
||||||
|
print(self.name + ": started()")
|
||||||
|
self.fps = FPS().start()
|
||||||
|
if self.next is not None:
|
||||||
|
self.next.onFirstFrame()
|
||||||
|
|
||||||
|
def stopped(self):
|
||||||
|
self.fps.stop()
|
||||||
|
print(self.name + ": stopped()")
|
||||||
|
print(self.name + ": Processed " + str(self.frames) + " frames")
|
||||||
|
print(self.name + ": FPS = " + str(self.frames/self.fps.elapsed()))
|
||||||
|
|
||||||
# abstractmethod
|
# abstractmethod
|
||||||
def process(self):
|
def process(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
if not self.thread.is_alive():
|
||||||
|
self.thread.start()
|
||||||
|
|
||||||
# should be called to exit thread
|
# should be called to exit thread
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.fps.stop()
|
if self.thread.is_alive():
|
||||||
print("Processed " + str(self.frames) + " frames")
|
if self.next is not None:
|
||||||
print("FPS = " + str(self.frames/self.fps.elapsed()))
|
self.next.stop()
|
||||||
self.cancel = True
|
self.cancel = True
|
||||||
self.thread.join()
|
self.thread.join()
|
||||||
if self.next is not None:
|
|
||||||
self.next.stop()
|
|
||||||
|
|
||||||
class RgbProcessorAdapter(object):
|
class RgbProcessorAdapter(object):
|
||||||
def __init__(self, resolution=(320, 240, 3)):
|
def __init__(self, resolution=(320, 240, 3)):
|
||||||
self.resolution = resolution
|
self.resolution = resolution
|
||||||
self.frameSize = resolution[0]*resolution[1]*resolution[2]
|
self.frameSize = resolution[0]*resolution[1]*resolution[2]
|
||||||
self.size = 0
|
self.size = 0
|
||||||
self.frames = 0
|
|
||||||
self.fps = None
|
self.fps = None
|
||||||
self.processors = []
|
self.processors = []
|
||||||
self.needRgbConversion = True
|
self.needRgbConversion = True
|
||||||
@@ -121,18 +138,15 @@ class RgbProcessorAdapter(object):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def write(self, data):
|
def write(self, data):
|
||||||
|
if data is None:
|
||||||
|
return
|
||||||
|
|
||||||
if self.size == 0:
|
if self.size == 0:
|
||||||
for proc in self.processors:
|
for proc in self.processors:
|
||||||
proc.onFirstFrame()
|
proc.onFirstFrame()
|
||||||
|
|
||||||
self.fps = FPS().start()
|
self.fps = FPS().start()
|
||||||
|
|
||||||
if data is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.size += len(data)
|
|
||||||
self.frames += len(data)/self.frameSize
|
|
||||||
|
|
||||||
res = (self.resolution[0], self.resolution[1])
|
res = (self.resolution[0], self.resolution[1])
|
||||||
|
|
||||||
if self.needRgbConversion:
|
if self.needRgbConversion:
|
||||||
@@ -140,6 +154,8 @@ class RgbProcessorAdapter(object):
|
|||||||
else:
|
else:
|
||||||
rgbData = data
|
rgbData = data
|
||||||
|
|
||||||
|
self.size += rgbData.size
|
||||||
|
|
||||||
for proc in self.processors:
|
for proc in self.processors:
|
||||||
proc.onData(rgbData)
|
proc.onData(rgbData)
|
||||||
|
|
||||||
@@ -149,16 +165,19 @@ class RgbProcessorAdapter(object):
|
|||||||
def flush(self):
|
def flush(self):
|
||||||
if self.size > 0:
|
if self.size > 0:
|
||||||
self.fps.stop()
|
self.fps.stop()
|
||||||
print("Recorded " + str(self.frames) + " frames (" + str(self.size) + " bytes)")
|
frames = self.size/self.frameSize
|
||||||
print("FPS = " + str(self.frames/self.fps.elapsed()))
|
print("Recorded " + str(frames) + " frames (" + str(self.size) + " bytes)")
|
||||||
|
print("FPS = " + str(frames/self.fps.elapsed()))
|
||||||
|
for proc in self.processors:
|
||||||
|
proc.onLastFrame()
|
||||||
|
|
||||||
if ("__main__" == __name__):
|
if ("__main__" == __name__):
|
||||||
import cv2
|
import cv2
|
||||||
|
|
||||||
# Unit test with to threaded processors
|
# Unit test with to threaded processors
|
||||||
class MyRgbProcess1(RgbProcess):
|
class MyRgbProcess1(RgbProcess):
|
||||||
def __init__(self, resolution=(320, 240, 3), numEntries=2, next=None):
|
def __init__(self, name, resolution=(320, 240, 3), numEntries=2, next=None):
|
||||||
super(MyRgbProcess1, self).__init__(resolution, numEntries, next)
|
super(MyRgbProcess1, self).__init__(name, resolution, numEntries, next)
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
data = self.read(1.0)
|
data = self.read(1.0)
|
||||||
@@ -173,8 +192,8 @@ if ("__main__" == __name__):
|
|||||||
self.next.write(cv2.cvtColor(gray_blurred,cv2.COLOR_GRAY2BGR))
|
self.next.write(cv2.cvtColor(gray_blurred,cv2.COLOR_GRAY2BGR))
|
||||||
|
|
||||||
class MyRgbProcess2(RgbProcess):
|
class MyRgbProcess2(RgbProcess):
|
||||||
def __init__(self, resolution=(320, 240, 3), numEntries=2, next=None):
|
def __init__(self, name, resolution=(320, 240, 3), numEntries=2, next=None):
|
||||||
super(MyRgbProcess2, self).__init__(resolution, numEntries, next)
|
super(MyRgbProcess2, self).__init__(name, resolution, numEntries, next)
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
data = self.read(1.0)
|
data = self.read(1.0)
|
||||||
@@ -191,8 +210,8 @@ if ("__main__" == __name__):
|
|||||||
camera.resolution = (320, 240)
|
camera.resolution = (320, 240)
|
||||||
camera.framerate = 60
|
camera.framerate = 60
|
||||||
frameDim = (camera.resolution[0], camera.resolution[1], 3)
|
frameDim = (camera.resolution[0], camera.resolution[1], 3)
|
||||||
myProcessor2 = MyRgbProcess2((240, 320, 3), 4)
|
myProcessor2 = MyRgbProcess2('Process 2', (240, 320, 3), 4)
|
||||||
myProcessor1 = MyRgbProcess1((240, 320, 3), 4, myProcessor2)
|
myProcessor1 = MyRgbProcess1('Process 1', (240, 320, 3), 4, myProcessor2)
|
||||||
myRgbProcessorAdapter = RgbProcessorAdapter(frameDim)
|
myRgbProcessorAdapter = RgbProcessorAdapter(frameDim)
|
||||||
myRgbProcessorAdapter.processorAdd(myProcessor1)
|
myRgbProcessorAdapter.processorAdd(myProcessor1)
|
||||||
camera.start_recording(myRgbProcessorAdapter, format="bgr")
|
camera.start_recording(myRgbProcessorAdapter, format="bgr")
|
||||||
|
|||||||
Executable
+51
@@ -0,0 +1,51 @@
|
|||||||
|
import time
|
||||||
|
import cv2
|
||||||
|
from threading import Thread
|
||||||
|
from picamera import PiCamera
|
||||||
|
from piCameraPipeline.PiCameraPipeline import RgbProcessorAdapter
|
||||||
|
|
||||||
|
class VideoSource(RgbProcessorAdapter):
|
||||||
|
def __init__(self, fileName, resolution, framerate):
|
||||||
|
super(VideoSource, self).__init__(resolution)
|
||||||
|
self.fileName = fileName
|
||||||
|
self.resolution = resolution
|
||||||
|
self.framerate = framerate
|
||||||
|
self.thread = None
|
||||||
|
self.camera = None
|
||||||
|
self.cancel = False
|
||||||
|
if fileName == 'piCamera':
|
||||||
|
self.camera = PiCamera()
|
||||||
|
self.camera.resolution = (self.resolution[0], self.resolution[1])
|
||||||
|
self.camera.framerate = self.framerate
|
||||||
|
else:
|
||||||
|
self.needRgbConversion = False
|
||||||
|
self.thread = Thread(target=self.fileReadThread)
|
||||||
|
|
||||||
|
def fileReadThread(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
if self.thread is not None:
|
||||||
|
if not self.thread.is_alive():
|
||||||
|
self.thread.start()
|
||||||
|
else:
|
||||||
|
self.camera.start_recording(self, format="bgr")
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self.thread is not None:
|
||||||
|
if self.thread.is_alive():
|
||||||
|
self.cancel = True
|
||||||
|
self.thread.join()
|
||||||
|
else:
|
||||||
|
self.camera.stop_recording()
|
||||||
|
|
||||||
|
def fileReadThread(self):
|
||||||
|
cap = cv2.VideoCapture(self.fileName)
|
||||||
|
while not self.cancel:
|
||||||
|
ret, frame = cap.read()
|
||||||
|
if ret:
|
||||||
|
self.write(frame)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
time.sleep(1.0/self.framerate)
|
||||||
|
self.flush()
|
||||||
+6
-6
@@ -10,8 +10,8 @@ if ("__main__" == __name__):
|
|||||||
|
|
||||||
# Unit test with to threaded processors
|
# Unit test with to threaded processors
|
||||||
class MyRgbProcess1(RgbProcess):
|
class MyRgbProcess1(RgbProcess):
|
||||||
def __init__(self, resolution=(320, 240, 3), numEntries=2, next=None):
|
def __init__(self, name, resolution=(320, 240, 3), numEntries=2, next=None):
|
||||||
super(MyRgbProcess1, self).__init__(resolution, numEntries, next)
|
super(MyRgbProcess1, self).__init__(name, resolution, numEntries, next)
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
data = self.read(1.0)
|
data = self.read(1.0)
|
||||||
@@ -26,8 +26,8 @@ if ("__main__" == __name__):
|
|||||||
self.next.write(cv2.cvtColor(gray_blurred,cv2.COLOR_GRAY2BGR))
|
self.next.write(cv2.cvtColor(gray_blurred,cv2.COLOR_GRAY2BGR))
|
||||||
|
|
||||||
class MyRgbProcess2(RgbProcess):
|
class MyRgbProcess2(RgbProcess):
|
||||||
def __init__(self, resolution=(320, 240, 3), numEntries=2, next=None):
|
def __init__(self, name, resolution=(320, 240, 3), numEntries=2, next=None):
|
||||||
super(MyRgbProcess2, self).__init__(resolution, numEntries, next)
|
super(MyRgbProcess2, self).__init__(name, resolution, numEntries, next)
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
data = self.read(1.0)
|
data = self.read(1.0)
|
||||||
@@ -44,8 +44,8 @@ if ("__main__" == __name__):
|
|||||||
camera.resolution = (320, 240)
|
camera.resolution = (320, 240)
|
||||||
camera.framerate = 60
|
camera.framerate = 60
|
||||||
frameDim = (camera.resolution[0], camera.resolution[1], 3)
|
frameDim = (camera.resolution[0], camera.resolution[1], 3)
|
||||||
myProcessor2 = MyRgbProcess2((240, 320, 3), 4)
|
myProcessor2 = MyRgbProcess2('Process 2', (240, 320, 3), 4)
|
||||||
myProcessor1 = MyRgbProcess1((240, 320, 3), 4, myProcessor2)
|
myProcessor1 = MyRgbProcess1('Process 1', (240, 320, 3), 4, myProcessor2)
|
||||||
myRgbProcessorAdapter = RgbProcessorAdapter(frameDim)
|
myRgbProcessorAdapter = RgbProcessorAdapter(frameDim)
|
||||||
myRgbProcessorAdapter.processorAdd(myProcessor1)
|
myRgbProcessorAdapter.processorAdd(myProcessor1)
|
||||||
camera.start_recording(myRgbProcessorAdapter, format="bgr")
|
camera.start_recording(myRgbProcessorAdapter, format="bgr")
|
||||||
|
|||||||
Reference in New Issue
Block a user