问题描述:
在做目标跟踪程序时,经常需要读写某个文件夹下的图像文件。可以使用WIN32_FIND_DATA结构体配合FindFirstFile函数以及FindNextFile函数实现对特定文件夹下的文件遍历,但是有时候我们的图像序列命名是有规律的,如img_00001.jpg等,能不能通过组合文件夹名+前缀+编号+后缀的方式实现文件的读取呢,可以!
编写函数,实现功能:在txt配置文件中指定图像序列的文件夹路径、结果文件夹路径、图像前缀、图像数目、起始编号、目标个数、目标位置。代码如下
/******************************************************************************
函数名:readConfig
功能:根据配置文件读取图像序列目录、图像前缀、图像扩展名、图像数目、开始编号,目标数目、目标位置。
参数:
configFileName- 配置文件路径,后缀为.txt
sourceDir - 图像序列文件夹名字
resultDir - 结果图像文件夹
imagePrefix - 前缀名
imageExt - 扩展名
imageNum - 图像数目
imageStartID - 序列开始编号
targetPos - 目标位置信息,存储目标上、下、左、右边界
targetNum - 目标数量
说明:
******************************************************************************/
bool readConfig(const char* configFileName,
char* sourceDir,
char* resultDir,
char * imagePrefix,
char *imageExt,
int& imageNum,
int& imageStartID,
RECT* targetPos,
int &targetNum )
{
fstream f;
char lineString[1000];
int readS=0;
f.open(configFileName, fstream::in);
if (f.bad())
{
return false;
}
char param1[200]; strcpy(param1,"");
char param2[200]; strcpy(param2,"");
char param3[200]; strcpy(param3,"");
/// 1.读取图像序列文件夹路径
// 注意:配置文件的第一行第三个参数才是文件夹路径。前两个参数是source_directory 和 "="号
f.getline(lineString, sizeof(lineString));
readS = sscanf (lineString, "%s %s %s", param1, param2, param3); //
strcpy(sourceDir,param3);
strcpy(param3,"");
// 2.读取结果文件夹路径,注意:配置文件的第2行第三个参数才是结果文件夹路径
f.getline(lineString, sizeof(lineString));
readS=sscanf (lineString, "%s %s %s", param1, param2, param3);
strcpy(resultDir,param3);
strcpy(param3,"");
/// 3.读取图像前缀
f.getline(lineString, sizeof(lineString));
readS=sscanf (lineString, "%s %s %s", param1, param2, param3);
strcpy(imagePrefix,param3);
strcpy(param3,"");
/// 4.读取图像扩展名
f.getline(lineString, sizeof(lineString));
readS=sscanf (lineString, "%s %s %s", param1, param2, param3);
strcpy(imageExt,param3);
strcpy(param3,"");
/// 5.读取图像数目
f.getline(lineString, sizeof(lineString));
readS=sscanf (lineString, "%s %s %d", param1, param2, &imageNum);
/// 6.读取第一帧图像编号,比如1
f.getline(lineString, sizeof(lineString));
readS=sscanf (lineString, "%s %s %d", param1, param2, &imageStartID);
/// 7.读取第一帧图像中的目标数量
f.getline(lineString, sizeof(lineString));
readS=sscanf (lineString, "%s %s %d", param1, param2, &targetNum);
/// 8.读取每个目标的位置,目标个数由上一步操作确定。
int x=0, y=0, w=0, h=0;
for (int i=0; i<targetNum; i++)
{
f.getline( lineString, sizeof(lineString) );
readS=sscanf (lineString, "%s %s %d %d %d %d", param1,param2, &x, &y, &w, &h);
targetPos[i].left = x;
targetPos[i].right = x + w;
targetPos[i].top = y;
targetPos[i].bottom = y + h;
}
return true;
}
要求:配置文件格式应该如下:
source_directory = E:\data #注释:此行为源文件夹路径,
result_directory = E:\data\result #注释:结果文件夹路径,在此文件夹下保存跟踪结果图像
imagePredix = #注释:此行imagePredix代表图像文件名字前缀
imageExtension = .jpg #注释:此行为图像文件扩展名,图像文件格式可以为.bmp或j.pg或.png
imageNum = 64 #注释:此行为图像文件数量,假如在源文件夹路径source_directory下有100个图像,则imageNum值为100
startID = 1 #注释:图像文件起始编号
targetNum = 3 #注释:需要跟踪的目标数目,最少为1,最多为10
targetPosition_1 = 479 337 87 86 #注释:第1个目标在第一帧图像中的位置信息
targetPosition_2 = 958 332 85 87 #注释:第2个目标在第一帧图像中的位置信息
targetPosition_3 = 1262 320 98 90 #注释:第3个目标在第一帧图像中的位置信息
最后,当需要在for循环中打开特定编号的文件时,使用如下命令,获取完整的文件路径:
sprintf(dstFileFullPath,"%s%s%d%s",fileDir,filePrefix,fileID,fileExt);
其中dstFileFullPath为一个char 数组,将要包含特定编号的图像序列文件。
获得文件名后,在使用相关程序打开文件即可。
当然,如果你喜欢使用xml配合tinyxml或者rapidxml,那么,可以达到更好的效果。
说明:以上代码参考了compressive tracking的c++实现程序的相关代码,原程序在http://www4.comp.polyu.edu.hk/~cslzhang/CT/CT.htm,致谢!