Python OpenCV - 在根据特定对象条件保存视频时,并非所有此类帧都被保存
Python OpenCV - while saving video based on a specific object condition not all such frames are getting saved
我在 Python 中使用 opencv 并尝试 record/save 仅当帧中存在特定类型的 object/label 时 record/save 来自视频的那些帧 'umbrella'
问题:
它正确地从它第一次在帧中发现提到 object/label 的实例开始保存帧,但如果 object/label 在接下来的几帧中不存在并且仅在几帧之后出现,那么那些框架没有保存到我正在保存的 mp4 文件中。
它只保存带有提到对象的第一个连续帧,不保存后面的帧。
After reading suggestions from this link I edited code by putting frame writing steps within a for-loop as shown below:
写一段我尝试即兴创作的代码
# saving video frame by frame
for frame_numb in range(total_frames):
if i == '':
pass
else:
if "umbrella" in label:
print("umbrella in labels")
# Issue causing part where I may need some change
out_vid.write(frame[frame_numb])
以上代码修改后的结果:
它只创建 256kb 的文件,并且文件无法打开/不写入任何内容
如果我对代码进行以下更改,那么它只会保存满足该条件的视频的第一帧,并在整个时间内运行同一帧
# saving video frame by frame
for frame_numb in range(total_frames):
if i == '':
pass
else:
if "umbrella" in label:
print("umbrella in labels")
# Issue causing part where I may need some change
out_vid.write(frame)
下面分享更大的代码块以供参考:
def vid_objects_detection(type=0, confidence_threshold=0.5, image_quality=416):
classes = []
# reading category names from coco text file and inserting in classes list
with open("coco.names", "r") as f:
classes = [line.strip() for line in f.readlines()]
net = cv2.dnn.readNet("yolov3-tiny.weights", "yolov3-tiny.cfg") # using tiny versions of weights & config file
layer_names = net.getLayerNames()
output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
# Loading video
cap = cv2.VideoCapture(type) # use 0 for webcam
_, frame = cap.read()
height, width, channels = frame.shape
# providing codec for writing frames to video
fourcc = cv2.VideoWriter_fourcc(*'MP4V')
# Write video with name & size. Should be of same size(width, height) as original video
out_vid = cv2.VideoWriter('obj_detect4_'+str(type), fourcc, 20.0, (width,height))
font = cv2.FONT_HERSHEY_COMPLEX_SMALL
starting_time = time.time()
frame_id = 0
while True:
_, frame = cap.read()
frame_id +=1
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
height, width, channels = frame.shape
blob = cv2.dnn.blobFromImage(frame, 0.00392, (image_quality, image_quality), (0, 0, 0), True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)
# For showing informations on screen
class_ids = []
confidences = []
boxes = []
for out in outs:
for detection in out:
# claculated scores, class_id, confidence
if confidence > confidence_threshold:
# claculatedd center_x, center_y, w,h,x,y
boxes.append([x, y, w, h])
confidences.append(float(confidence))
class_ids.append(class_id)
print("confidences:", confidences)
print(class_ids)
print("boxes", boxes)
indexes = cv2.dnn.NMSBoxes(boxes, confidences, confidence_threshold, 0.4)
for i in range(len(boxes)):
if i in indexes:
x, y, w, h = boxes[i]
label = str(classes[class_ids[i]])
elapsed_time = time.time() - starting_time
fps = frame_id / elapsed_time
time_display = time.strftime("%a, %d%b%Y %H:%M:%S", time.localtime())
cv2.putText(frame,"|FPS: " + str(round(fps,3)), (10, 40), font, 1, (0,255,0), 1)
print(fps)
# saving video frame by frame
if i == '':
pass
else:
if 'umbrella' in label:
out_vid.write(frame)
key = cv2.waitKey(5)
if key == 27:
break
cap.release()
out_vid.release()
cv2.destroyAllWindows()
# calling function
vid_objects_detection("walking.mp4")
我在代码中删减了一些小的计算并插入了注释以减少代码的长度
有时视频编解码器会执行所谓的关键帧压缩。这意味着,一帧被完整存储,比如每 10 帧,而其间的所有其他帧都存储为更改或增量。在这些情况下,当您尝试仅保存这些中间帧时,它们可能无法保存。但是在这些情况下,如果您按顺序遍历每一帧,保存帧就会起作用。
也许您可以注释掉行 out_vid = cv2.VideoWriter('obj_detect4_'+str(type), fourcc, 20.0, (width,height))
,然后根据您的情况尝试从网络摄像头流中保存帧。
我在 Python 中使用 opencv 并尝试 record/save 仅当帧中存在特定类型的 object/label 时 record/save 来自视频的那些帧 'umbrella'
问题:
它正确地从它第一次在帧中发现提到 object/label 的实例开始保存帧,但如果 object/label 在接下来的几帧中不存在并且仅在几帧之后出现,那么那些框架没有保存到我正在保存的 mp4 文件中。
它只保存带有提到对象的第一个连续帧,不保存后面的帧。
After reading suggestions from this link I edited code by putting frame writing steps within a for-loop as shown below:
写一段我尝试即兴创作的代码
# saving video frame by frame
for frame_numb in range(total_frames):
if i == '':
pass
else:
if "umbrella" in label:
print("umbrella in labels")
# Issue causing part where I may need some change
out_vid.write(frame[frame_numb])
以上代码修改后的结果:
它只创建 256kb 的文件,并且文件无法打开/不写入任何内容
如果我对代码进行以下更改,那么它只会保存满足该条件的视频的第一帧,并在整个时间内运行同一帧
# saving video frame by frame
for frame_numb in range(total_frames):
if i == '':
pass
else:
if "umbrella" in label:
print("umbrella in labels")
# Issue causing part where I may need some change
out_vid.write(frame)
下面分享更大的代码块以供参考:
def vid_objects_detection(type=0, confidence_threshold=0.5, image_quality=416):
classes = []
# reading category names from coco text file and inserting in classes list
with open("coco.names", "r") as f:
classes = [line.strip() for line in f.readlines()]
net = cv2.dnn.readNet("yolov3-tiny.weights", "yolov3-tiny.cfg") # using tiny versions of weights & config file
layer_names = net.getLayerNames()
output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
# Loading video
cap = cv2.VideoCapture(type) # use 0 for webcam
_, frame = cap.read()
height, width, channels = frame.shape
# providing codec for writing frames to video
fourcc = cv2.VideoWriter_fourcc(*'MP4V')
# Write video with name & size. Should be of same size(width, height) as original video
out_vid = cv2.VideoWriter('obj_detect4_'+str(type), fourcc, 20.0, (width,height))
font = cv2.FONT_HERSHEY_COMPLEX_SMALL
starting_time = time.time()
frame_id = 0
while True:
_, frame = cap.read()
frame_id +=1
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
height, width, channels = frame.shape
blob = cv2.dnn.blobFromImage(frame, 0.00392, (image_quality, image_quality), (0, 0, 0), True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)
# For showing informations on screen
class_ids = []
confidences = []
boxes = []
for out in outs:
for detection in out:
# claculated scores, class_id, confidence
if confidence > confidence_threshold:
# claculatedd center_x, center_y, w,h,x,y
boxes.append([x, y, w, h])
confidences.append(float(confidence))
class_ids.append(class_id)
print("confidences:", confidences)
print(class_ids)
print("boxes", boxes)
indexes = cv2.dnn.NMSBoxes(boxes, confidences, confidence_threshold, 0.4)
for i in range(len(boxes)):
if i in indexes:
x, y, w, h = boxes[i]
label = str(classes[class_ids[i]])
elapsed_time = time.time() - starting_time
fps = frame_id / elapsed_time
time_display = time.strftime("%a, %d%b%Y %H:%M:%S", time.localtime())
cv2.putText(frame,"|FPS: " + str(round(fps,3)), (10, 40), font, 1, (0,255,0), 1)
print(fps)
# saving video frame by frame
if i == '':
pass
else:
if 'umbrella' in label:
out_vid.write(frame)
key = cv2.waitKey(5)
if key == 27:
break
cap.release()
out_vid.release()
cv2.destroyAllWindows()
# calling function
vid_objects_detection("walking.mp4")
我在代码中删减了一些小的计算并插入了注释以减少代码的长度
有时视频编解码器会执行所谓的关键帧压缩。这意味着,一帧被完整存储,比如每 10 帧,而其间的所有其他帧都存储为更改或增量。在这些情况下,当您尝试仅保存这些中间帧时,它们可能无法保存。但是在这些情况下,如果您按顺序遍历每一帧,保存帧就会起作用。
也许您可以注释掉行 out_vid = cv2.VideoWriter('obj_detect4_'+str(type), fourcc, 20.0, (width,height))
,然后根据您的情况尝试从网络摄像头流中保存帧。