必要的文件夹
└── mydataset
└── VOCDataset
├── Annotations #存放xml文件,与JPEGImages中的图片一一对应,解释图片的内容等等
├── ImageSets #该目录下存放的都是txt文件,txt文件中每一行包含一个图片的名称,末尾会加上±1表示正负样本
│ ├── Action
│ ├── Layout
│ ├── Main
│ └── Segmentation
├── JPEGImages #存放源图片
├── SegmentationClass #存放的是图片,语义分割相关
└── SegmentationObject #存放的是图片,实例分割相关
保证:JPEGImages下存放图片,Annotations下存放与图片名对应的xml文件。ImageSets/Main下的trainval.txt和test.txt存放不带有图片后缀的名字。
#!/bin/bash
root_dir= mydataset下的文件夹 ####这里改到你数据集的路径,绝对路径
sub_dir=ImageSets/Main
bash_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
for dataset in trainval test
do
dst_file=$bash_dir/$dataset.txt
if [ -f $dst_file ]
then
rm -f $dst_file
fi
for name in VOCDataset ###数据集名称
do
if [[ $dataset == "test" && $name == "VOC2012" ]]
then
continue
fi
echo "Create list for $name $dataset..."
dataset_file=$root_dir/$name/$sub_dir/$dataset.txt
img_file=$bash_dir/$dataset"_img.txt"
cp $dataset_file $img_file
sed -i "s/^/$name\/JPEGImages\//g" $img_file
sed -i "s/$/.jpg/g" $img_file
label_file=$bash_dir/$dataset"_label.txt"
cp $dataset_file $label_file
sed -i "s/^/$name\/Annotations\//g" $label_file
sed -i "s/$/.xml/g" $label_file
paste -d' ' $img_file $label_file >> $dst_file
rm -f $label_file
rm -f $img_file
done
# Generate image name and size infomation.
if [ $dataset == "test" ]
then
./caffe-ssd/build/tools/get_image_size $root_dir $dst_file $bash_dir/$dataset"_name_size.txt"#这个路径也要改下
fi
# Shuffle trainval file.
if [ $dataset == "trainval" ]
then
rand_file=$dst_file.random
cat $dst_file | perl -MList::Util=shuffle -e 'print shuffle();' > $rand_file
mv $rand_file $dst_file
fi
done
在工程的根目录下运行create_list.sh,运行后,会在create_list.sh同一目录上生成trainval.txt、test.txt、test_name_size.txt。
cur_dir=$(cd $( dirname ${BASH_SOURCE[0]} ) && pwd )
root_dir=$cur_dir/../..
cd $root_dir
redo=1
data_root_dir= mydataset的目录下
dataset_name="VOCDataset"
mapfile="$root_dir/data/mydataset/labelmap_voc.prototxt" #修改到你保存lambelmap_voc.protxt的路径
anno_type="detection"
db="lmdb"
min_dim=0
max_dim=0
width=0
height=0
extra_cmd="--encode-type=jpg --encoded"
if [ $redo ]
then
extra_cmd="$extra_cmd --redo"
fi
for subset in test trainval
do
python $root_dir/scripts/create_annoset.py --anno-type=$anno_type \
--label-map-file=$mapfile --min-dim=$min_dim --max-dim=$max_dim --resize-width=$width \
--resize-height=$height --check-label $extra_cmd $data_root_dir $root_dir/data/mydataset/$subset.txt \ #trainval.txt和test.txt的路径。
$data_root_dir/$dataset_name/$db/$dataset_name"_"$subset"_"$db examples/$dataset_name
done
在项目根目录下运行create_data.sh。(在根目录下运行是为了防止生成的lmdb出现no such file)。运行后,生成examples/VOCDataset/VOCDataset_trainval_lmdb和examples/VOCDataset/VOCDataset_test_lmdb。
import lmdb
import caffe
env.open("./examples/VOC0712/VOC0712_trainval_lmdb")
txn = env.begin()
datum = caffe.proto.caffe_pb2.AnnotatedDatum()
for key, value in txn.cursor():
datum.ParseFromString(value)
label = datum.annotation_group
标注的label获取,annotated_data_layer.cpp。
AnnotatedDataParameter& anno_data_param
有以下参数可设置:
message AnnotatedDataParameter {
// Define the sampler.
repeated BatchSampler batch_sampler = 1;
// Store label name and label id in LabelMap format.
optional string label_map_file = 2;
// If provided, it will replace the AnnotationType stored in each
// AnnotatedDatum.
optional AnnotatedDatum.AnnotationType anno_type = 3;
optional int32 yolo_data_type = 4 [default = 0];
optional float yolo_data_jitter = 5 [default = 0.3];
optional bool train_diffcult = 6 [default = true];
optional bool single_class =7 [default = true]; // for yolo segementation
optional int32 seg_scales = 8 [default = 8]; // for yolo segementation
optional int32 seg_resize_width = 9 [default = 0]; // for yolo segementation
optional int32 seg_resize_height = 10 [default = 0]; // for yolo segementation
}
// Read a data point, and use it to initialize the top blob.
AnnotatedDatum& anno_datum = *(reader_.full().peek());
Annotated可选参数
message AnnotatedDatum {
enum AnnotationType {
BBOX = 0;
BBOXandSeg = 1;
LANE = 2;
}
optional Datum datum = 1;
// If there are "rich" annotations, specify the type of annotation.
// Currently it only supports bounding box.
// If there are no "rich" annotations, use label in datum instead.
optional AnnotationType type = 2;
// Each group contains annotation for a particular class.
repeated AnnotationGroup annotation_group = 3;
}
message AnnotationGroup {
optional int32 group_label = 1;
repeated Annotation annotation = 2;
}
AnnotationGroup anno_group; 声明
anno_group.annotation_size; 获取大小 保存多个Annotation
const Annotation& anno = anno_group.annotation(a);
const NormalizedBBox& bbox = anno.bbox();
message NormalizedBBox {
optional float xmin = 1;
optional float ymin = 2;
optional float xmax = 3;
optional float ymax = 4;
optional int32 label = 5;
optional bool difficult = 6;
optional float score = 7;
optional float size = 8;
}
可在blob.hpp和blob.cpp中查看。
blob成员变量
protected:
shared_ptr<SyncedMemory> data_;// 存放数据
shared_ptr<SyncedMemory> diff_;//存放梯度
vector<int> shape_; //存放形状
int count_; //数据个数
int capacity_; //数据容量
blob常用成员函数
const Dtype* cpu_data() const; //cpu使用的数据
void set_cpu_data(Dtype* data);//用数据块的值来blob里面的data。
const Dtype* gpu_data() const;//返回不可更改的指针,下同
const Dtype* cpu_diff() const;
const Dtype* gpu_diff() const;
Dtype* mutable_cpu_data();//返回可更改的指针,下同
Dtype* mutable_gpu_data();
Dtype* mutable_cpu_diff();
Dtype* mutable_gpu_diff();
//带mutable_开头的意味着可以对返回的指针内容进行更改,而不带mutable_开头的返回const 指针,不能对其指针的内容进行修改,
int offset(const int n, const int c = 0, const int h = 0,const int w = 0) const
// 通过n,c,h,w 4个参数来计算一维向量的偏移量。
Dtype data_at(const int n, const int c, const int h,const int w) const//通过n,c,h,w 4个参数来来获取该向量位置上的值。
Dtype diff_at(const int n, const int c, const int h,const int w) const//同上
inline const shared_ptr<SyncedMemory>& data() const {
CHECK(data_);
return data_;//返回数据,不能修改
}
inline const shared_ptr<SyncedMemory>& diff() const {
CHECK(diff_);
return diff_;//返回梯度,不能修改
}
Reshape(...)//reshape 有多种多态的实现,可以是四个数字,长度为四的vector,其它blob等。
if (count_ > capacity_) {
capacity_ = count_;
data_.reset(new SyncedMemory(capacity_ * sizeof(Dtype)));
diff_.reset(new SyncedMemory(capacity_ * sizeof(Dtype)));
}//当空间不够的时候,需要扩大容量,reset。
void Blob<Dtype>::CopyFrom(const Blob& source, bool copy_diff, bool reshape)