我有几个视频,每个视频大约 5 分钟,以及注释数据,其中包含有关每个对象在每个帧号处的边界框坐标的信息。我正在尝试阅读视频并在边界框的中心之间逐帧绘制线条(当当前帧号与地面实况数据中的数字匹配时)。我不想在批处理过程中执行此操作,但每 30 或 60 帧对我有用。这是我的代码:
VideoCapture capture(path_video);
if (!capture.isOpened()){
cout << "Failed to capture frame/Open the file" << "n";
return 0;
}
bool stop(false);
while(!stop){
capture >> frame;
if (frame.data==NULL) {
break;
}
double rate = capture.get(CV_CAP_PROP_FPS);
int delay = 1000/rate;
frmNum = (capture.get(CV_CAP_PROP_POS_FRAMES));
for (int i=0 ; i<db.size() ; i++){//db is a vector of vector that has annotation data for each object splited in inner vectors , and is sorted ascendingly on start frame number of objects.
if (!db[i].empty()){
for (int j=1 ; j<db[i].size() ; j++){
if(frmNum == db[i][j-1].currFrame){
cv::line(frame, db[i][j-1].pnt, db[i][j].pnt,Scalar(255,0,0),2);
}
else{
break;
}
}
}
}
imshow("Video", frame);
int key = waitKey(delay);
if (key==27){
break;
}
我检查了一下,我的 if 条件变为真,但视频上没有画线。我想我没有看到线条,因为框架正在变化并且绘制的线条被新框架清除,但我想不出另一种方法。感谢您的帮助。
在每一帧上绘制注释,并且您不介意这些信息在某些情况下可能"过时",我会执行以下操作:
- 具有
- 称为"overlay"的全局图像变量,该变量将保存注释的最新(相对于当前帧数)表示形式,并且与视频流中的单个帧具有相同的大小
- 维护一个名为"last_object_annotation_idx"的索引数组,该数组将为每个对象存储已查看/使用的注释的最后一个索引(每个对象最初设置为 -1)
- 在主循环的每次迭代中,更新"last_object_annotation_idx"数组(即,对于每个对象,检查当前帧号是否与下一个注释的"currFrame"字段匹配 - 我正在使用注释数组排序的信息)
- 如果数组发生了更改,请使用从"last_object_annotation_idx"引用的注释重绘叠加图像
- 最后,将叠加图像添加到帧并显示结果。
此外,在 if 语句中
if(frmNum == db[i][j-1].currFrame){
cv::line(frame, db[i][j-1].pnt, db[i][j].pnt,Scalar(255,0,0),2);
}
else{
break;
}
"中断"不是有点错误吗?这意味着如果第一次检查失败,您将脱离循环,因此在这种情况下,您将看不到超过第一个索引的任何内容。