最近在写yolo_kcf,前面的测试其实还算比较顺利,关于状态切换,今天遇到了一个坑,现在还没有解决,写出来记录一下,看是不是自己知识有盲区啊。
大概的背景:yolo的视频检测的代码主要是用c写的,kcf的代码主要是cpp写的,这里遇到的问题主要设计两个文件:
- demo.c
主要是这么一个代码:
void *detect_in_thread(void *ptr)
{
if(tracking==0)
{
running = 1; //就是一个标志位,表示正在进行当前的进程吧?
float nms = .4; //nms是最大值检测的
layer l = net->layers[net->n-1];
float *X = buff_letter[(buff_index+2)%3].data; //数据,这就是直接图像数据的指针了
network_predict(net, X); //网络预测
/*
if(l.type == DETECTION){
get_detection_boxes(l, 1, 1, demo_thresh, probs, boxes, 0);
} else */
remember_network(net);
detection *dets = 0;
int nboxes = 0;
dets = avg_predictions(net, &nboxes);
//获得检测的结果
//注释掉的这一部分应该是以前的版本
/*
int i,j;
box zero = {0};
int classes = l.classes;
for(i = 0; i < demo_detections; ++i){
avg[i].objectness = 0;
avg[i].bbox = zero;
memset(avg[i].prob, 0, classes*sizeof(float));
for(j = 0; j < demo_frame; ++j){
axpy_cpu(classes, 1./demo_frame, dets[j][i].prob, 1, avg[i].prob, 1);
avg[i].objectness += dets[j][i].objectness * 1./demo_frame;
avg[i].bbox.x += dets[j][i].bbox.x * 1./demo_frame;
avg[i].bbox.y += dets[j][i].bbox.y * 1./demo_frame;
avg[i].bbox.w += dets[j][i].bbox.w * 1./demo_frame;
avg[i].bbox.h += dets[j][i].bbox.h * 1./demo_frame;
}
//copy_cpu(classes, dets[0][i].prob, 1, avg[i].prob, 1);
//avg[i].objectness = dets[0][i].objectness;
}
*/
//非极大值抑制,
if (nms > 0) do_nms_obj(dets, nboxes, l.classes, nms);
//打印一些参数
//帧率和识别的目标
printf("\033[2J");
printf("\033[1;1H");
printf("\nFPS:%.1f\n",fps);
printf("Objects:\n\n");
image display = buff[(buff_index+2) % 3]; //需要显示的当前的图片
//图上面画框之类的函数,但是这里实际实际上并没有显示,显示的话还是需要用opencv来做
draw_detections(display, dets, nboxes, demo_thresh, demo_names, demo_alphabet, demo_classes);
box bbox=dets[0].bbox;
track_box.x=bbox.x*display.w;
track_box.y=bbox.y*display.h;
track_box.w=bbox.w*display.w;
track_box.h=bbox.h*display.h;
/*
printf("from (x,y)=(%d,%d)\t",xx,yy);
printf("(w,h)=(%d,%d)\n",ww,hh);
printf("%d\n",nboxes);
*/
/*这里一定要来判断bboxes是否是大于0的,如果不是的话,
那么dets[0]和dets[0].prob[0]这两个指针都是空的,把空指针传入printf就只能等着程序崩溃了。
陷阱就是虽然指针是野的,但是是有值的,可以进行计算,我一开始写的是:
float prob=dets[0].prob[0]*100;
printf("%f\n",prob);
第一句计算是不会报错的,第二句直接崩溃。
*/
if(nboxes>0)
{
printf("%f\n",dets[0].prob[0]*100);
if(dets[0].prob[0]*100>=95) //如果检测到的置信率大于95%的话就转入跟踪
{
tracking=1; //进入跟踪状态
track_begin=1; //这是第一次进入跟踪状态
}
}
//释放内存应该是
free_detections(dets, nboxes);
demo_index = (demo_index + 1)%demo_frame;
running = 0;
return 0;
}
//这里不用else,也就是说我是需要上面的运行结束之后,当前的帧就要转换到tracking模式下来做第一帧
//图像的显示函数是不能自己来写的,因为这个东西全是交给线程来做的,所以这里只能修改不能做显示,要不会卡死的。
if(tracking==1)
{
//printf("this is tracking process!!!\n");
image current_img = buff[(buff_index+2) % 3];
//printf("track_begin%d\t\n",track_begin); //这里看着是1啊,但是到后面就直接成了172了,神奇
//printf("bbox:%d\t%d\t%d\t%d\n",track_box.x,track_box.y,track_box.w,track_box.h);
kcf(current_img,track_box,track_begin,tracking);
}
}
没心思的看的话我简化一下:
static tracking=0;
static track_begin=0;
void *detect_in_thread(void *ptr)
{
if(tracking=0)
{
if(一定条件)
{
tracking=1;
track_begin=1;
}
}
if(tracking=1)
{
kcf(一些参数,tracking,track_begin);
//kcf是另外一个文件里的一个函数,需要track_begin来判断
}
}
- image_opencv.cpp
void kcf(image img,c_rect &bbox,int isBegin,int tracking)
{
cout<<"is Begin:\t"<<isBegin<<endl;
cout<<"is tracking \t"<<tracking<<endl;
if(isBegin==1)
{
cout<<"hello world!"<<endl;
Mat first_frame=image_to_mat(img); //图片转换为mat格式
cout<<"frame_sz:\t"<<first_frame.size()<<endl;
Rect first_rect=Rect(bbox.x,bbox.y,bbox.w,bbox.h); //box格式的位置转换为rect格式的
tracker.init(first_rect,first_frame); //初始化跟踪器
}
else
{
Mat current_frame=image_to_mat(img); //获取当前帧的视频,这里是没有问题的,图像也能获取
//目前的问题是调用这个更新就会报错,我也不知道是怎么回事
//cv::Rect tracking_res=tracker.update(current_frame);
//cout<<tracking_res<<endl;
}
}
这里面主要是如果是track_begin=1的话需要进入if来初始化跟踪器,一开始老是不对我也每发现是什么理由,直到我说不会是isBegin数字不对吧,所以我在最开始输出了一下,竟然是172,为了对比我把tracking也传入进来了,是没有问题的,所以我就懵逼了!如图,我也不知道是啥原因,我再看看,找不到原因就只能想办法规避这个坑了。