学习opencv训练分类器,网上看到有提imageclipper这个辅助工具的,可以很方便的截取ROI并保存,记录位置和大小等相关信息,在准备正样本时非常有用。
其项目主页:http://code.google.com/p/imageclipper/
imageclipper是多平台的,windows和linux下均可以编译,其主页上有详细的介绍如何在相应平台下编译,并且使用方法,生成正样本描述文件的脚本命令都有介绍。
但该项目好久都没更新了,最新的提供下载的版本都是2008年12月份的。
我用svn下下来的,版本是102:svn checkout http://imageclipper.googlecode.com/svn/trunk/ imageclipper-read-only
imageclipper依赖boost这个准标准C++库,编译前需安装这个库,我用archlinux,安装命令:pacman -S boost,会安装boost和boost-libs两个包,一个是头文件,一个是库。
按照主页里讲的先大概修改了一下Makefile,不过仍然不出意外的编译报错了:
root@topgun ~/Works/imageclipper/imageclipper-read-only/src
# make
g++ `pkg-config --cflags opencv` -I /usr/include/boost -I. -o imageclipper.o -c imageclipper.cpp
In file included from imageclipper.cpp:43:0:
filesystem.h: 在函数‘std::string filesystem::realpath(const string&)’中:
filesystem.h:60:23: 错误:‘class boost::filesystem::path’没有名为‘native_file_string’的成员
return fspath.native_file_string();
^
filesystem.h: 在函数‘std::string filesystem::dirname(const string&)’中:
filesystem.h:66:37: 错误:‘class boost::filesystem::path’没有名为‘native_file_string’的成员
return fspath.branch_path().native_file_string();
^
filesystem.h: 在函数‘std::string filesystem::basename(const string&)’中:
filesystem.h:72:28: 错误:could not convert ‘boost::filesystem::path::leaf() const()’ from ‘boost::filesystem::path’ to ‘std::string {aka std::basic_string<char>}’
return fspath.leaf();
^
filesystem.h: 在函数‘std::vector<std::basic_string<char> > filesystem::filelist(const string&, const std::vector<std::basic_string<char> >&, std::string)’中:
filesystem.h:129:44: 错误:‘class boost::filesystem::path’没有名为‘native_file_string’的成员
if( match_extensions( filename.native_file_string(), extensions ) ) {
^
filesystem.h:131:50: 错误:‘class boost::filesystem::path’没有名为‘native_file_string’的成员
filelist.push_back( filename.native_file_string() );
^
filesystem.h:133:50: 错误:‘class boost::filesystem::path’没有名为‘native_file_string’的成员
filelist.push_back( filename.native_file_string() );
^
filesystem.h:135:50: 错误:‘class boost::filesystem::path’没有名为‘native_file_string’的成员
filelist.push_back( filename.native_file_string() );
^
filesystem.h:137:50: 错误:‘class boost::filesystem::path’没有名为‘native_file_string’的成员
filelist.push_back( filename.native_file_string() );
^
filesystem.h:139:50: 错误:‘class boost::filesystem::path’没有名为‘native_file_string’的成员
filelist.push_back( filename.native_file_string() );
^
make: *** [imageclipper.o] 错误 1
这个是因为boost库更新了,一些方法的名字改了,imageclipper用的boost是1.36.0版本的,而我安装的是1.54.0。
在项目的issue页面提供了一个filesystem.h的patch,地址:http://code.google.com/p/imageclipper/issues/detail?id=9
不过也许这个是对于zip下载的,我用svn下载的有三行对不上,自己手动修改了下,其实也就替换两个地方:
一是native_file_string()替换为string(),二是leaf()替换为filename().string()。
改了这个之后,就能编译出目标文件了。
但是,链接出错:
# make
g++ `pkg-config --cflags opencv` -I /usr/include/boost -I. -o imageclipper.o -c imageclipper.cpp
g++ -o imageclipper imageclipper.o `pkg-config --libs opencv` -L /usr/lib
imageclipper.o:在函数‘__static_initialization_and_destruction_0(int, int)’中:
imageclipper.cpp:(.text+0x6cc1):对‘boost::system::generic_category()’未定义的引用
imageclipper.cpp:(.text+0x6ccb):对‘boost::system::generic_category()’未定义的引用
imageclipper.cpp:(.text+0x6cd5):对‘boost::system::system_category()’未定义的引用
imageclipper.o:在函数‘boost::filesystem::path::branch_path() const’中:
imageclipper.cpp:(.text._ZNK5boost10filesystem4path11branch_pathEv[_ZNK5boost10filesystem4path11branch_pathEv]+0x14):对‘boost::filesystem::path::parent_path() const’未定义的引用
imageclipper.o:在函数‘boost::filesystem::exists(boost::filesystem::path const&)’中:
imageclipper.cpp:(.text._ZN5boost10filesystem6existsERKNS0_4pathE[_ZN5boost10filesystem6existsERKNS0_4pathE]+0x1c):对‘boost::filesystem::detail::status(boost::filesystem::path const&, boost::system::error_code*)’未定义的引用
imageclipper.o:在函数‘boost::filesystem::is_directory(boost::filesystem::path const&)’中:
imageclipper.cpp:(.text._ZN5boost10filesystem12is_directoryERKNS0_4pathE[_ZN5boost10filesystem12is_directoryERKNS0_4pathE]+0x1c):对‘boost::filesystem::detail::status(boost::filesystem::path const&, boost::system::error_code*)’未定义的引用
imageclipper.o:在函数‘boost::filesystem::is_other(boost::filesystem::path const&)’中:
imageclipper.cpp:(.text._ZN5boost10filesystem8is_otherERKNS0_4pathE[_ZN5boost10filesystem8is_otherERKNS0_4pathE]+0x1c):对‘boost::filesystem::detail::status(boost::filesystem::path const&, boost::system::error_code*)’未定义的引用
imageclipper.o:在函数‘boost::filesystem::is_symlink(boost::filesystem::path const&)’中:
imageclipper.cpp:(.text._ZN5boost10filesystem10is_symlinkERKNS0_4pathE[_ZN5boost10filesystem10is_symlinkERKNS0_4pathE]+0x1c):对‘boost::filesystem::detail::symlink_status(boost::filesystem::path const&, boost::system::error_code*)’未定义的引用
imageclipper.o:在函数‘boost::filesystem::is_regular(boost::filesystem::path const&)’中:
imageclipper.cpp:(.text._ZN5boost10filesystem10is_regularERKNS0_4pathE[_ZN5boost10filesystem10is_regularERKNS0_4pathE]+0x1c):对‘boost::filesystem::detail::status(boost::filesystem::path const&, boost::system::error_code*)’未定义的引用
imageclipper.o:在函数‘boost::filesystem::create_directories(boost::filesystem::path const&)’中:
imageclipper.cpp:(.text._ZN5boost10filesystem18create_directoriesERKNS0_4pathE[_ZN5boost10filesystem18create_directoriesERKNS0_4pathE]+0x15):对‘boost::filesystem::detail::create_directories(boost::filesystem::path const&, boost::system::error_code*)’未定义的引用
imageclipper.o:在函数‘boost::filesystem::detail::dir_itr_imp::~dir_itr_imp()’中:
imageclipper.cpp:(.text._ZN5boost10filesystem6detail11dir_itr_impD2Ev[_ZN5boost10filesystem6detail11dir_itr_impD5Ev]+0x22):对‘boost::filesystem::detail::dir_itr_close(void*&, void*&)’未定义的引用
imageclipper.o:在函数‘boost::filesystem::directory_iterator::directory_iterator(boost::filesystem::path const&)’中:
imageclipper.cpp:(.text._ZN5boost10filesystem18directory_iteratorC2ERKNS0_4pathE[_ZN5boost10filesystem18directory_iteratorC5ERKNS0_4pathE]+0x4e):对‘boost::filesystem::detail::directory_iterator_construct(boost::filesystem::directory_iterator&, boost::filesystem::path const&, boost::system::error_code*)’未定义的引用
imageclipper.o:在函数‘boost::filesystem::directory_iterator::increment()’中:
imageclipper.cpp:(.text._ZN5boost10filesystem18directory_iterator9incrementEv[_ZN5boost10filesystem18directory_iterator9incrementEv]+0x15):对‘boost::filesystem::detail::directory_iterator_increment(boost::filesystem::directory_iterator&, boost::system::error_code*)’未定义的引用
imageclipper.o:在函数‘boost::filesystem::extension(boost::filesystem::path const&)’中:
imageclipper.cpp:(.text._ZN5boost10filesystem9extensionERKNS0_4pathE[_ZN5boost10filesystem9extensionERKNS0_4pathE]+0x15):对‘boost::filesystem::path::extension() const’未定义的引用
imageclipper.o:在函数‘boost::filesystem::basename(boost::filesystem::path const&)’中:
imageclipper.cpp:(.text._ZN5boost10filesystem8basenameERKNS0_4pathE[_ZN5boost10filesystem8basenameERKNS0_4pathE]+0x15):对‘boost::filesystem::path::stem() const’未定义的引用
imageclipper.o:在函数‘filesystem::basename(std::string const&)’中:
imageclipper.cpp:(.text._ZN10filesystem8basenameERKSs[_ZN10filesystem8basenameERKSs]+0x27):对‘boost::filesystem::path::filename() const’未定义的引用
collect2: 错误:ld 返回 1
make: *** [imageclipper] 错误 1
这个是因为链接boost库,要显式的指明库文件名,pacman -Ql boost-libs命令可以看到/usr/lib/libboost_system.so和/usr/lib/libboost_filesystem.so两个库文件,
修改Makefile文件,LFLAGS行修改为:
LFLAGS = `pkg-config --libs opencv` -L /usr/lib -lboost_system -lboost_filesystem
就可以编译通过了。
总结就是需要修改两个文件一个是Makefile和filesystem.h,都是因为boost版本更新需要修改,这里我用svn diff命令做了这两个文件的patch,放到我资源里面了:
Makefile补丁:http://download.csdn.net/detail/topgun38/6216579
filesystem.h补丁:http://download.csdn.net/detail/topgun38/6216599
附一:
linux常用生成patch命令:
diff -u one one_new > one_new.patch
为文件one生成统一格式的patch文件,文件one打上该patch后会变成one_new。-u参数指定生成统一格式的patch。比普通格式包含更多信息且更通用。
linux常用打patch命令:
patch -p0 < /path/to/one_new.patch
p参数后面的数字跟patch文件中的路径和当前敲命令时路径相关,如果当前路径与patch文件中路径连接刚好到相应文件,则数字为0,如果路径重叠了一层,则为1,类推。
如patch文件中路径为a/b/one,而当前正处在b目录下,那么应该用-p2。
附二:
imageclipper程序截图:
附三:
imageclipper程序截取的ROI存储名称默认如下格式:
meinv2.png_0000_0182_0093_0051_0035.png
这个格式可以用参数更改,对于默认参数,项目主页上提供了一个命令将截取的ROI文件的文件名来生成正样本描述文件的命令,如下:
$ find imageclipper/*_*_* -exec basename \{\} \; | perl -pe \
's/([^_]*).*_0*(\d+)_0*(\d+)_0*(\d+)_0*(\d+)\.[^.]*$/$1 $2 $3 $4 $5\n/g' \
| tee clipping.txt
它得到的结果是下面这个格式的:
image.jpg 68 47 89 101
image.jpg 87 66 90 80
image.jpg 95 105 33 32
image.jpg 109 93 65 90
image.jpg 117 97 52 95
但在opencv的文档中说明描述文件在文件名后应该跟目标数目,然后才是目标坐标,所以可以在上面命令的$1和$2之间加上" 1 ",即:
find imageclipper/*_*_* -exec basename \{\} \; | perl -pe 's/([^_]*).*_0*(\d+)_0*(\d+)_0*(\d+)_0*(\d+)\.[^.]*$/$1 1 $2 $3 $4 $5\n/g' | tee clipping.txt