-
作者: 知明所以 • Milo
-
日期: 2013年7月27日
1 环境准备
1.1 基本工具:
-
Visual Studio 2012 必装
-
opencv 2.4+ 必装 ( 目前是2.4.6, 下载链接 ). ( 假设已安装完毕, opencv安装目录以下用 {opencv} 表示 )
-
cygwin 必装 ( 安装教程, 网上一抓一大把, 就不贴链接了. 记得安装 perl )
-
CMake 必装 ( 下载链接, 用来编译 opencv )
1.2 辅助工具:
-
imageclipper 工具. 此工具能快速的从原始图片中截取待识别区域, 生成只包含待识别区域的图片. ( 下载地址 )
-
opencv_createsamples 工具. 在文件夹 {cvbuild}/bin/Release/opencv_createsamples.exe 中.
-
mergevec 工具. 用来把多个 *.vec 文件生成一个 *.vec 文件. ( 下载地址 )
-
createtrainsamples 工具, 用来快速生成大量测试样本. ( 下载地址 )
-
如果以上地址无法打开, 这里有以上工具的合集. ( 百度网盘下载 )
-
此文中用到的所有命令, 均以sh脚本文件保存在这里( 百度网盘下载, 下文用 “脚本附件”表示此附件 ). 您可以省去很多编写脚本的麻烦
1.3 项目文件结构如下:
2 详细步骤
2.1 编译 opencv
因为这一步骤比较长, 被我单独开贴到这里了.
此步骤务必完成, 否则后续步骤无法执行
编译 opencv 的目标位置, 在下文中用 {cvbuild} 表示
2.2 制作样本
2.2.1 负样本
目标: 生成 背景描述文件 bg.txt
步骤:
-
下载负样本文件. ( 忘记从哪里下载的了, 事先申明这图片库不是我制作的, 请大家不要用于商业用途. 百度盘下载 )
-
解压文件到某处. 进入文件夹, 执行以下命令:12
cd
.
/samples/negtive/
find
./ -name
"*.png"
> .
/bg
.txt
得到 bg.txt. 即为负样本文件. ( 脚本附件/S2-fetchNegtiveImage.sh )
2.2.2 正样本
目标: 生成正样本的 *.vec 样本描述文件
2.2.2.1 用 imageclipper 截取待识别区域
运行命令:( 假设源图片放在 ./samples/positive/src/ 文件夹中 )
如果没有特殊说明, 文中所有的命令均在 cygwin 终端中执行.
1
|
./imageclipper/imageclipper.exe ./samples/positive/src/
-o
./samples/positive/%i__
%
x__
%
y__
%
w__
%
h__.png
|
( 脚本附件/S1-clipPositiveImage.sh )
在命令行中输入
1
|
./imageclipper/imageclipper.exe
|
可以看到 imageclipper 的使用说明. 咱们主要关心一下 –o 参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
-o
<output_format = imgout_format or vidout_format>
Determine the output file path format.
This is a syntax sugar for
-i
and
-v
.
Format Expression)
%d - dirname of the original
%i - filename of the original without extension
%e - filename extension of the original
%x - upper
-left
x coord
%y - upper
-left
y coord
%w - width
%
h
- height
%
r
- rotation degree
%. - shear deformation in x coord
%, - shear deformation in y coord
%f - frame number (for video)
Example) ./$i_
%
04x_
%
04y_
%
04w_
%
04h.%e
Store into software directory and use image
type
of the original.
|
-o 参数主要来控制生成图片的文件名.
比如咱们这里的 –o 参数为 “%i__%x__%y__%w__%h__.png”.
就表示生成文件的文件名为 “原文件名__x坐标__y坐标__宽度__高度__.png”.
生成文件在文件夹:./samples/positive/ 中:
2.2.2.2 用 opencv_createsamples 对截取出的区域生成样本描述文件 *.vec
opencv 官方文档中对 opencv_createsamples 的使用描述见这里
在终端中输入 opencv_createsamples 不加任何参数, 查看使用帮助:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
$ ./opencvTools/opencv_createsamples.exe
Usage: D:\vsWorkspace\trainClassifier\opencvTools\opencv_createsamples.exe
[
-info
<collection_file_name>]
[
-img
<image_file_name>]
[
-vec
<vec_file_name>]
[
-bg
<background_file_name>]
[
-num
<number_of_samples = 1000>]
[
-bgcolor
<background_color = 0>]
[
-inv
] [
-randinv
] [
-bgthresh
<background_color_threshold = 80>]
[
-maxidev
<max_intensity_deviation = 40>]
[
-maxxangle
<max_x_rotation_angle = 1.100000>]
[
-maxyangle
<max_y_rotation_angle = 1.100000>]
[
-maxzangle
<max_z_rotation_angle = 0.500000>]
[
-show
[<scale = 4.000000>]]
[
-w
<sample_width = 24>]
[
-h
<sample_height = 24>]
|
我们需要用到的参数有:
1
2
3
4
5
6
7
8
9
|
[
-img
<image_file_name>] //样本图片url
[
-vec
<vec_file_name>] //生成 vec 文件名
[
-bg
<background_file_name>] // 背景图片描述文件.( 即一个文本文件, 里面每一行是一个背景文件的url )
[
-num
<number_of_samples = 1000>] // 对每一个图片生成多少个变形后的图片.
[
-maxxangle
<max_x_rotation_angle = 1.100000>] // 最大x方向翻转
[
-maxyangle
<max_y_rotation_angle = 1.100000>] // 最大y方向翻转
[
-maxzangle
<max_z_rotation_angle = 0.500000>] // 最大z方向翻转
[
-w
<sample_width = 24>]
[
-h
<sample_height = 24>] //这里的w和h在以后会多次用到, 一定要保证和这里的相等. 否则会失败
|
下面使用 openc_createasamples 工具来对每一个目标文件生成对应的 *.vec 样本描述文件
新建 ./S3-createsamples.sh 文件. 内容如下: ( 脚本附件/S3-createsamples.sh )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#!/bin/sh
positive_dir=
"./samples/positive/"
list=($(find ./samples/positive/
-name
"*.png"
))
length of filelist: ${
#list[@]}
content=
""
for file in ${list[@]}
do
echo
==========================
name=${file
##*/}
echo
filename:
$name
arr=${name//__/ }
arr=(
$arr
)
echo
${arr[@]}
echo
width: ${arr[3]}, height: ${arr[4]}
line=
"$name"
content=
"$content$name.vec \n"
vecname=${name//./_}
./opencvTools/opencv_createsamples.exe
-vec
./samples/positive/
$vecname
.vec –bg ./samples/negtive/bg.txt
-img
$file
-w
50
-h
25
-num
5
echo
==========================
done
listfile=$positive_dir
"vec_list.txt"
targetfile=$positive_dir
"target.vec"
echo
$listfile
echo
$targetfile
find $positive_dir
-name
"*png.vec"
>
$listfile
./imageclipper/mergevec.exe
$listfile
$targetfile
-w
50
-h
25
|
如果需要, 根据 1.3 中本项目的文件结构图, 将上面的文件路径改成你需要的路径.
执行命令:
1
|
$ .
/S3-createSamples
.sh
|
打开文件夹, 看到一列 *.vec 文件就对啦~~
2.2.2.3 用 mergevec 工具合并 *.vec 文件
细心的您执行完 步骤2.2.2.2 之后, 就会发现上图已经有合并后的 target.vec 了.
为了方便, 我已经把合并 vec 的步骤写到 S3-createsamples.sh 文件里去了. 看看这个文件的最后两行就知道啦.
输入以下命令可以看到 mergevec 的使用帮助:
1
2
3
4
5
|
$ .
/imageclipper/mergevec
.exe
Usage: D:\vsWorkspace\trainClassifier\imageclipper\mergevec.exe
<collection_file_of_vecs>
<output_vec_filename>
[-show] [-w <sample_width = 24>] [-h <sample_height = 24>]
|
2.2.3 测试样本
目标: 生成大量带有待识别区域的测试图片, 在这些图片中, 待识别区域的位置都已知.
方法: 把证样本图片中的待识别区域, 经过缩放拉伸翻转后, 按随机位置贴在背景图片上, 并记录下待识别区域在背景图片上的位置.
假设我们想训练一个识别嘴巴的识别器. 生成的测试样本如下:
利用我们训练的识别器, 对这些图片进行识别. 得到的结果, 跟实际情况相比较, 即可知道识别器的识别率和性能.
创建 S5-createTestSample.sh 内容如下: ( 脚本附件/S5-createTestSample.sh )
1
2
3
4
5
6
|
cd
.
/samples/test/
find
..
/negtive/
-name
"*.png"
> negtive.dat
#正样本
find
..
/positive/
-maxdepth 1 -name
"*.png"
> positive.dat
# 负样本
perl ../..
/imageclipper/createsamples
.pl positive.dat negtive.dat tests 1000 \
"../../opencvTools/opencv_createsamples -bgcolor 0 -bgthresh 0 -maxxangle 1.1 -maxyangle 1.1 -maxzangle 0.5 maxidev 40"
find
tests/ -name
"info.dat"
-
exec
cat
\{\} \; > tests.dat
# merge info files
|
运行脚本文件 S5-createTestSample.sh . 查看 ./samples/test/tests 文件夹, 就能看到各种样本图片啦~~
样本图片列表存放在:
./samples/test/tests.dat
里. 如果内容如下:
1
2
3
4
5
|
tests
/IMG_20130718_150032__228__548__107__58__
.png
/0001_0044_0065_0071_0071
.jpg 1 44 65 71 71
tests
/IMG_20130718_150032__228__548__107__58__
.png
/0002_0068_0232_0125_0125
.jpg 1 68 232 125 125
tests
/IMG_20130718_150032__228__548__107__58__
.png
/0003_0126_0071_0112_0112
.jpg 1 126 71 112 112
tests
/IMG_20130718_150032__228__548__107__58__
.png
/0004_0043_0136_0057_0057
.jpg 1 43 136 57 57
...
|
证明你成功的创建了测试样本!
2.3 训练过程
目标: 利用 opencv_haartraining 工具训练识别器
执行以下命令来训练识别器:
1
2
3
4
5
6
|
.
/opencvTools/opencv_haartraining
.exe \
-data .
/teeath_haartraining
\
-vec .
/samples/positive/target
.vec \
-
bg
.
/samples/negtive/bg
.txt \
-w 50 -h 25 -nsplits 2 -npos 30 -nneg 200 \
-nonsym -mem 512 -mode ALL -minhitrate 0.95 -maxfalsealarm 0.5
|
( 脚本附件/S4-training.sh )
注意: 此步骤可能因为正样本过少或者负样本过少而导致错误. 如果出现错误, 请使用更多样本进行尝试.
训练过程可能要持续好几天, 请耐心等待.
opencv_haartraining 的官方使用说明见这里
输入以下命令可查看简要参数说明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
$ .
/opencvTools/opencv_haartraining
.exe
Usage: D:\vsWorkspace\trainClassifier\opencvTools\opencv_haartraining.exe
-data <dir_name>
-vec <vec_file_name>
-
bg
<background_file_name>
[-
bg
-vecfile]
[-npos <number_of_positive_samples = 2000>]
[-nneg <number_of_negative_samples = 2000>]
[-nstages <number_of_stages = 14>]
[-nsplits <number_of_splits = 1>]
[-mem <memory_in_MB = 200>]
[-sym (default)] [-nonsym]
[-minhitrate <min_hit_rate = 0.995000>]
[-maxfalsealarm <max_false_alarm_rate = 0.500000>]
[-weighttrimming <weight_trimming = 0.950000>]
[-eqw]
[-mode <BASIC (default) | CORE | ALL>]
[-w <sample_width = 24>]
[-h <sample_height = 24>]
[-bt <DAB | RAB | LB | GAB (default)>]
[-err <misclass (default) | gini | entropy>]
[-maxtreesplits <max_number_of_splits_in_tree_cascade = 0>]
[-minpos <min_number_of_positive_samples_per_cluster = 500>]
|
2.4 测试性能
目标: 通过用大量测试数据进行实际测试, 得到识别器的识别率和识别性能
原理: 已在 2.3.3 讲过. 可回看参考.
执行命令:
1
|
.
/opencvTools/opencv_performance
.exe -data teeath_haartraining/ -w 50 -h 25 -info samples
/test/tests
.dat -ni
|
( 脚本附件/S6-test.sh )
3 参考
3.1 Tutorial: OpenCV haartraining
3.3 Merge vec files created by createsamples
3.4 Cascade Classifier Training ( opencv offical document )