我必须编写一个代码,使用将每个帧转换为黑白的等式将视频文件从RGB转换为黑白。 我必须在多处理和队列的同时并在Opencv的帮助下完成这项工作。 我确实编写了代码,但是在无限循环中终止进程时遇到了问题。当我完成阅读框架时,如何终止这些过程,因为父亲正在等待孩子们完成并且他们永远不会完成。 这是我的代码..
#! /usr/bin/python
import numpy as np
import cv2
import multiprocessing as mp
import time
def read_frames(q1, q2):
while True:
NumAndFrame = q1.get()
frame = NumAndFrame[1]
if frame == 'Done':
# Here is my problem,this is not working!!!
processes.terminate()
break
j = NumAndFrame[0]
R = frame[:, :, 0]
G = frame[:, :, 1]
B = frame[:, :, 2]
y = (np.uint8)((0.299 * R) + (0.587 * G) + (0.114 * B))
q2.put((j, y))
if __name__ == '__main__':
start = time.time()
q1 = mp.Queue()
q2 = mp.Queue()
processes = []
for i in range(4):
processes.append(mp.Process(target=read_frames, args=(q1, q2)))
for p in processes:
p.start()
# feed the processes
# read input file and send to the processes the frames:
cap = cv2.VideoCapture('gou.avi')
lines = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
cols = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
fps = int(cap.get(cv2.CAP_PROP_FPS))
fourcc_ver = int(cap.get(cv2.CAP_PROP_FOURCC))
out = cv2.VideoWriter('output.avi', fourcc_ver, fps, (cols, lines), False)
j = 1
while (cap.isOpened()):
ret, frame = cap.read()
# as long as new frames are there
if ret == True:
q1.put((j, frame))
j += 1
# if cv2.waitKey(1) & 0xFF == ord('q'):
# break
else:
break
q1.put((1, 'Done'))
for p in processes:
p.join()
result = []
for p in processes:
result.append(q2.get())
result.sort()
result = []
for r in result:
result.append(r[1])
for i in result:
out.write(i)
print i
# Release everything if job is finished
print 'final finish'
cap.release()
out.release()
cv2.destroyAllWindows()
答案 0 :(得分:0)
您可能希望尝试将问题与较小的示例配对,但如果您只是想在无限期运行的循环中停止计算,则可以将Ctrl-C发送垃圾邮件直至其停止。或者,您可以关闭shell窗口。
答案 1 :(得分:0)
没有经过测试,出于同样的原因,其他人给出了评论: 你应该打电话给#34;终止"在主部分中的每个进程上,而不是在子函数中调用它:
...
for p in processes:
p.terminate()
p.join()
答案 2 :(得分:0)
考虑使用multiprocessing.Pool,因为它可以帮助您解决大部分问题。
你需要一个"完成"每个子进程的消息。孩子应该向父母发送某种确认并终止。您还需要在worker中使用某种错误处理策略,以便异常不会以静默方式退出该worker。
您还有其他问题,例如此代码会将进程数与处理的邮件数混淆。
for p in processes:
result.append(q2.get())
相反,您应该阅读所有消息,计算它在途中获得的终止确认的数量,以便您知道何时停止阅读。
你的剧本很长,而且我不会假装我已经把它弄好了(请保持友好并在将来发布更小的例子!)但这是第一次去清理它
#! /usr/bin/python
import numpy as np
import cv2
import multiprocessing as mp
import time
def read_frames(q1, q2):
while True:
try:
NumAndFrame = q1.get()
frame = NumAndFrame[1]
if frame == 'Done':
q2.put('Done')
break
j = NumAndFrame[0]
R = frame[:, :, 0]
G = frame[:, :, 1]
B = frame[:, :, 2]
y = (np.uint8)((0.299 * R) + (0.587 * G) + (0.114 * B))
q2.put((j, y))
except Exception, e:
q2.put('Error: ' + str(e))
if __name__ == '__main__':
start = time.time()
q1 = mp.Queue()
q2 = mp.Queue()
processes = []
for i in range(4):
processes.append(mp.Process(target=read_frames, args=(q1, q2)))
for p in processes:
p.start()
# feed the processes
# read input file and send to the processes the frames:
cap = cv2.VideoCapture('gou.avi')
lines = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
cols = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
fps = int(cap.get(cv2.CAP_PROP_FPS))
fourcc_ver = int(cap.get(cv2.CAP_PROP_FOURCC))
out = cv2.VideoWriter('output.avi', fourcc_ver, fps, (cols, lines), False)
j = 1
while (cap.isOpened()):
ret, frame = cap.read()
# as long as new frames are there
if ret == True:
q1.put((j, frame))
j += 1
# if cv2.waitKey(1) & 0xFF == ord('q'):
# break
else:
break
for _ in len(processes):
q1.put((1, 'Done'))
for p in processes:
p.join()
result = []
done_count = 0
while done_count < len(processes):
data = q2.get()
if isinstance(data, basetring) and data == 'Done':
done_count += 1
else:
result.append(data)
result.sort()
# What??? don't overwrite result here!
result = []
for r in result:
result.append(r[1])
for i in result:
out.write(i)
print i
# Release everything if job is finished
print 'final finish'
cap.release()
out.release()
cv2.destroyAllWindows()
您最终将整个返回的数据集保留在父级中,这样您就可能遇到内存问题。并且因为(1)你有一个大的数据有效负载被从父到子复制回来,并且(2)numpy释放gil,你可能会发现线程比进程更好。在创建工作人员时,只需用Thread
代替Process
即可快速检查。