0. 主要工作:
1. 指令
1.1 TUM 数据集
1
|
./darknet detect_tum_batch [path_of_cfg] [path_of_weight] [path_of_dataset] [output_folder] [-thresh thresh]
|
1
|
./darknet detect_tum_batch cfg/yolov3.cfg yolov3.weights /home/wu/data/dataset/rgbd_dataset_freiburg1_desk/ /home/wu/data/ -thresh 0.4
|
- 注意:请在 [output_folder] 下创建
yolo_imgs
和 yolo_txts
文件夹来存放绘制了检测框的图片和检测框 txt 信息。
1.2 KITTI 数据集
1
|
./darknet detect_kitti_batch [path_of_cfg] [path_of_weight] [path_of_dataset] [output_folder] [-thresh thresh]
|
例如:
1
|
./darknet detect_kitti_batch cfg/yolov3.cfg yolov3.weights /home/wu/data/dataset/kitti/color/07/ /home/wu/data/ -thresh 0.4
|
- 注意:
- ① 请在 [output_folder] 下创建
yolo_imgs
和 yolo_txts
文件夹来存放绘制了检测框的图片和检测框 txt 信息;
- ② 在
test_detector_kitti_batch()
函数中默认采用的是 image_2
kitti 彩色数据集,如果使用 gray 数据集,可以将 image_2
改成 image_0
或 image_1
。
- 其他数据集:可仿照改动的函数写。
2. TUM 数据集
2.1 在 darknet.c 中添加指令参数
- 具体代码:darknet.c
- 在 main 函数中添加输入的第二个参数 detect_tum_batch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
else if (0 == strcmp(argv[1], "detect_tum_batch"))
{
// 读取阈值,默认为 0.5.
float thresh = find_float_arg(argc, argv, "-thresh", .5);
// @PARAM input_folder 输入数据集路径.
char *input_folder = (argc > 4) ? argv[4]: 0;
// @PARAM output_folder 输出结果存放路径.
char *output_folder = (argc > 5) ? argv[5]: 0;
// 开始处理.
test_detector_tum_batch( "cfg/coco.data",
argv[2], /* 网络模型 */
argv[3], /* 权重文件 */
input_folder, /* 输入数据集路径 */
output_folder, /* 输出的结果路径 */
thresh,
.5);
}
|
2.2 在 detector.c 中添加读取图片函数
- 具体代码:detector.c
- 在 detector.c 中添加上一步中用到的函数
1
2
3
4
5
6
7
8
|
void test_detector_tum_batch( char *datacfg, /* cfg/coco.data */
char *cfgfile, /* 网络模型 */
char *weightfile, /* 权重文件 */
char *input_folder, /* 输入数据集路径 */
char *output_folder,/* 输出结果保存路径 */
float thresh, /* 置信度阈值 */
float hier_thresh)
{……}
|
- 下面是处理的主要步骤。
2.2.1 读取数据集路径下的 rgb.txt 文件
- 由于给出的路径是
~/dataset/rgbd_dataset_freiburg1_desk/
,数据集图片存放在 ~/dataset/rgbd_dataset_freiburg1_desk/rgb
,图片名存放在 ~/dataset/rgbd_dataset_freiburg1_desk/rgb.txt
中,首先读取 rgb.txt
文件:
1
2
3
4
5
|
// NOTE 读取图像文件列表 rgb.txt. rgb_txt_path = ~/dataset/rgbd_dataset_freiburg1_desk/rgb.txt
char buff[256];
char *rgb_txt_path = buff;
strncpy(rgb_txt_path, input_folder, 256); // input_folder 还是 ~/dataset/rgbd_dataset_freiburg3_long_office_household/
FILE *fp_rgb_txt = fopen(strcat(rgb_txt_path,"rgb.txt"), "r");
|
2.2.2 读取图片文件名
rgb.txt
存储的内容形式如下,不考虑前三行,后面每行分别为时间戳和文件名:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# color images
# file: 'rgbd_dataset_freiburg1_desk.bag'
# timestamp filename
1305031452.791720 rgb/1305031452.791720.png
1305031452.823674 rgb/1305031452.823674.png
1305031452.859642 rgb/1305031452.859642.png
1305031452.891726 rgb/1305031452.891726.png
1305031452.923715 rgb/1305031452.923715.png
1305031452.959701 rgb/1305031452.959701.png
1305031452.991647 rgb/1305031452.991647.png
1305031453.023650 rgb/1305031453.023650.png
1305031453.059754 rgb/1305031453.059754.png
1305031453.091704 rgb/1305031453.091704.png
|
- 读取 19-43 列的图片文件名 img_name,再添加路径得到 input_img_name
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
int img_counter = -4; // rgb.txt 文件前三行无效.
while(!feof(fp_rgb_txt))
{
img_counter++;
memset(szTest, 0, sizeof(szTest));
fgets(szTest, sizeof(szTest) - 1, fp_rgb_txt); // 包含了换行符
// 前三行无效不存储,但得遍历读取,所以这个判断在上两行后面.
if( img_counter < 0)
continue;
strncpy(img_name, szTest+22, 17); // 每行前面 18位为时间戳,后面是文件名.
sprintf(input_img_name, "%srgb/%s.png", input_folder, img_name);
printf("文件名: %s\n", input_img_name);
}
fclose(fp_rgb_txt);
|
- 输出检测的图片结果,输出在
output_folder/yolo_imgs
中
1
2
3
4
5
6
|
// NOTE 输出图片.
strncpy(output_file, output_folder, 256);
char frame_index_c3[256];
//sprintf(frame_index_c3,"/yolo_imgs/%04d_yolo_%.2f",img_counter,thresh); // 0001_yolo2_0.50.jpg
sprintf(frame_index_c3,"yolo_imgs/%s",img_name); // 1905140001.223000.jpg
char * result_img = strcat(output_file,frame_index_c3);
|
3. KITTI 数据集
3.1 在 darknet.c 中添加指令参数
- 与 TUM 数据集类似,修改指令名和调用的函数名即可:detect_kitti_batch,test_detector_kitti_batch()。
3.2 在 detector.c 中添加读取并检测图像的函数
- 与 TUM 数据集类似,创建
test_detector_kitti_batch()
函数;
- 读取图像按照 6 位数序号来读取:
1
2
3
4
|
// STEP 1. 得到输入文件
// 读取输入的图像文件:~/color/21/image_2/000001.png
sprintf(input_img_name, "%simage_2/%06d.png", input_folder, num); // color image_2,gray image_0
printf("输入文件名: %s\n", input_img_name);
|
- 输出结果的文件名有两种存储方式:
- 第一种是按序号命名(默认情况),结果保存为:
000001.jpg
和 000001.txt
;
- 第二种是按照时间戳命名,结果保存为:
0.10387.jpg
和 0.10387.txt
;
- 可在
test_detector_kitti_batch()
函数中选择
1
2
3
4
5
6
7
8
9
10
11
12
|
// 【方法 ①】: 以序号命名
printf("文件序号: %06d\n", num);
sprintf(output_file_name, "%06d", num);
// // 【方法 ②】: 以时间戳命名
// // 逐行读取 txt 文件的时间戳:1.036224e-01.
// memset(szTest, 0, sizeof(szTest));
// fgets(szTest, sizeof(szTest) - 1, fp_rgb_txt); // 包含了换行符
// strncpy(output_file_name, szTest, 12);
// // 将时间戳转换成十进制
// double tmp_name = strtod(output_file_name, NULL); // note strtod() 转换成 lf 十进制类型.
// // 保留 5 位小数.
// sprintf(output_file_name, "%.5lf", tmp_name);
|
4. 在 image.c 中添加保存结果函数
- 具体代码:image.c
- 此函数仿写的
draw_detections()
,具体详见:
1
2
3
4
5
6
7
8
9
|
void draw_save_detections( image im,
detection *dets,
int num,
float thresh,
char **names,
image **alphabet,
int classes,
FILE *save_txt)
{……}
|
- 分别保存 类别、左上角坐标 + 宽 + 长、置信度,也可以修改为类别在 coco.name 中的编号,左上角和右下角坐标
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// NOTE 左上角坐标和右下脚坐标
int left = (b.x-b.w/2.)*im.w;
int top = (b.y-b.h/2.)*im.h;
int right = (b.x+b.w/2.)*im.w;
int bot = (b.y+b.h/2.)*im.h;
if(left < 0) left = 0;
if(right > im.w-1) right = im.w-1;
if(top < 0) top = 0;
if(bot > im.h-1) bot = im.h-1;
// NOTE 分别写入类别和坐标
// fprintf(save_txt,"%s\t%d\t%d\t%d\t%d\t%.2f\n", names[class], left, top, right-left, bot-top, dets[i].prob[class]);
fprintf(save_txt,"%d %d %d %d %d\n", class, left, top, right-left, bot-top);
|
- 输出 txt 结果,保存格式:类别 ID 左上角.x 左上角.y 长 宽 [置信度]
1
2
3
|
66 70 294 260 185 0.794691
64 255 258 63 38 0.813716
62 224 0 243 234 0.610995
|
- 可指定只保存某种类型的结果
1
2
3
4
5
6
|
// NOTE 只筛选出 "cup" 和 "bottle" 类别.
// if ((strcmp(names[class], "cup") != 0)&&(strcmp(names[class], "bottle") != 0))
// {continue;}
// 只选出 car.
if (strcmp(names[class], "car") != 0)
continue;
|
2019.03.11
wuyanminmax@gmail.com