我讀出OSX上一個攝像頭,它正常工作與這個簡單的腳本:如何在OSX的獨立進程中讀取攝像頭?
import cv2
camera = cv2.VideoCapture(0)
while True:
try:
(grabbed, frame) = camera.read() # grab the current frame
frame = cv2.resize(frame, (640, 480)) # resize the frame
cv2.imshow("Frame", frame) # show the frame to our screen
cv2.waitKey(1) # Display it at least one ms before going to the next frame
except KeyboardInterrupt:
# cleanup the camera and close any open windows
camera.release()
cv2.destroyAllWindows()
print "\n\nBye bye\n"
break
我現在想讀在一個單獨的進程的視頻,我有腳本這是一個很長時間和正確地讀出在Linux上的一個單獨的進程中視頻:
import numpy as np
import time
import ctypes
import argparse
from multiprocessing import Array, Value, Process
import cv2
class VideoCapture:
"""
Class that handles video capture from device or video file
"""
def __init__(self, device=0, delay=0.):
"""
:param device: device index or video filename
:param delay: delay between frame captures in seconds(floating point is allowed)
"""
self._cap = cv2.VideoCapture(device)
self._delay = delay
def _proper_frame(self, delay=None):
"""
:param delay: delay between frames capture(in seconds)
:param finished: synchronized wrapper for int(see multiprocessing.Value)
:return: frame
"""
snapshot = None
correct_img = False
fail_counter = -1
while not correct_img:
# Capture the frame
correct_img, snapshot = self._cap.read()
fail_counter += 1
# Raise exception if there's no output from the device
if fail_counter > 10:
raise Exception("Capture: exceeded number of tries to capture the frame.")
# Delay before we get a new frame
time.sleep(delay)
return snapshot
def get_size(self):
"""
:return: size of the captured image
"""
return (int(self._cap.get(int(cv2.CAP_PROP_FRAME_HEIGHT))),
int(self._cap.get(int(cv2.CAP_PROP_FRAME_WIDTH))), 3)
def get_stream_function(self):
"""
Returns stream_function object function
"""
def stream_function(image, finished):
"""
Function keeps capturing frames until finished = 1
:param image: shared numpy array for multiprocessing(see multiprocessing.Array)
:param finished: synchronized wrapper for int(see multiprocessing.Value)
:return: nothing
"""
# Incorrect input array
if image.shape != self.get_size():
raise Exception("Capture: improper size of the input image")
print("Capture: start streaming")
# Capture frame until we get finished flag set to True
while not finished.value:
image[:, :, :] = self._proper_frame(self._delay)
# Release the device
self.release()
return stream_function
def release(self):
self._cap.release()
def main():
# Add program arguments
parser = argparse.ArgumentParser(description='Captures the video from the webcamera and \nwrites it into the output file with predefined fps.', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-output', dest="output", default="output.avi", help='name of the output video file')
parser.add_argument('-log', dest="log", default="frames.log", help='name of the log file')
parser.add_argument('-fps', dest="fps", default=25., help='frames per second value')
# Read the arguments if any
result = parser.parse_args()
fps = float(result.fps)
output = result.output
log = result.log
# Initialize VideoCapture object and auxilary objects
cap = VideoCapture()
shape = cap.get_size()
stream = cap.get_stream_function()
# Define shared variables(which are synchronised so race condition is excluded)
shared_array_base = Array(ctypes.c_uint8, shape[0] * shape[1] * shape[2])
frame = np.ctypeslib.as_array(shared_array_base.get_obj())
frame = frame.reshape(shape[0], shape[1], shape[2])
finished = Value('i', 0)
# Start processes which run in parallel
video_process = Process(target=stream, args=(frame, finished))
video_process.start() # Launch capture process
# Sleep for some time to allow videocapture start working first
time.sleep(2)
# Termination function
def terminate():
print("Main: termination")
finished.value = True
# Wait for all processes to finish
time.sleep(1)
# Terminate working processes
video_process.terminate()
# The capturing works until keyboard interrupt is pressed.
while True:
try:
# Display the resulting frame
cv2.imshow('frame', frame)
cv2.waitKey(1) # Display it at least one ms before going to the next frame
time.sleep(0.1)
except KeyboardInterrupt:
cv2.destroyAllWindows()
terminate()
break
if __name__ == '__main__':
main()
這工作在Linux上很好,但在OSX我有麻煩,因爲它似乎無法做到創建cv2.VideoCapture(device)
對象的.read()
(存儲在var self._cap
)。
經過一番搜索後,我發現this SO answer,它建議使用Billiard,這是pythons多處理的替代品,據推測它有一些非常有用的改進。因此,在該文件的頂部,我只是我以前多進口後增加進口(有效覆蓋multiprocessing.Process
):
from billiard import Process, forking_enable
,只是在video_process
變量的實例之前,我用forking_enable
如下:
forking_enable(0) # Supposedly this is all I need for billiard to do it's magic
video_process = Process(target=stream, args=(frame, finished))
所以在這個版本(here on pastebin)然後,我又跑了文件,這給了我這個錯誤:
pickle.PicklingError: Can't pickle : it's not found as main.stream_function
搜索該錯誤導致我到an SO question with a long list of answers其中一個給了我建議使用dill serialization lib來解決這個問題。但是,該庫應該與Pathos multiprocessing fork一起使用。所以,我只是試圖改變我的多進口線從
from multiprocessing import Array, Value, Process
到
from pathos.multiprocessing import Array, Value, Process
但這些都不Array
,Value
和Process
似乎在pathos.multiprocessing
包存在。
從這一點我完全失去了。我正在尋找那些我幾乎沒有足夠知識的東西,而且我甚至不知道我需要再去搜索或調試的方向。
那麼比我更光明的靈魂能幫助我在單獨的過程中捕捉視頻嗎?歡迎所有提示!
嘗試'mp4v'作爲你的fourcc。 –
@MarkSetchell - 但在多處理代碼中,我甚至沒有試圖寫視頻,因爲我甚至無法從網絡攝像頭讀出它。問題是閱讀,而不是寫作。我還會刪除最初腳本中的文字,以免混淆人物。你有什麼想法在多處理代碼中讀取網絡攝像頭有什麼問題嗎? – kramer65
我是'pathos'和'dill'作者。你可能想嘗試'multiprocess',它是'pathos'下的庫,但是與'multiprocessing'具有完全相同的接口。你會發現'Array','Value'和'Process'對象。 –