代码笔记:caffereid利用训练好的模型提取特征

set -e
if [ ! -n "$1" ] ;then
    echo "\$1 is empty, default is 0"
    gpu=0
else
    echo "use $1-th gpu"
    gpu=$1
fi
#base_model=caffenet
base_model=vgg_reduce
#base_model=googlenet
#base_model=res50
feature_name=fc7
#feature_name=pool5/7x7_s1
#feature_name=pool5
model_file=./models/market1501/$base_model/snapshot/${base_model}.full_iter_18000.caffemodel

python examples/market1501/testing/extract_feature.py \
    examples/market1501/lists/test.lst \
    examples/market1501/datamat/test.lst.fc7.mat \
    examples/market1501/datamat/test.lst.score.mat \
    --gpu $gpu \
    --model_def ./models/market1501/$base_model/dev.proto \
    --feature_name $feature_name \
    --pretrained_model $model_file \
    --mean_value 97.8286,99.0468,105.606

python examples/market1501/testing/extract_feature.py \
    examples/market1501/lists/query.lst \
    examples/market1501/datamat/query.lst.fc7.mat \
    examples/market1501/datamat/query.lst.score.mat \
    --gpu $gpu \
    --model_def ./models/market1501/$base_model/dev.proto \
    --feature_name $feature_name \
    --pretrained_model $model_file \
    --mean_value 97.8286,99.0468,105.606

extract_feature.py内容如下:

import numpy as np
import os
import sys
import argparse
import glob
import time
import _init_paths
from units import SClassifier
import caffe
import scipy.io as sio


def load_txt(xfile):
    img_files = []
    labels = []
    for line in open(xfile):
        line = line.strip('\n').split(' ')
        assert(len(line) == 2)
        img_files.append(line[0])
        labels.append(int(float(line[1])))
    return img_files, labels

def main(argv):·

    parser = argparse.ArgumentParser()
    # Required arguments: input and output files.
    #由于没有设置default,因此这些参数在命令行中是必须的,否则会报错
    parser.add_argument(
        "input_file",
        help="Input image, directory"
    )
    parser.add_argument(
        "feature_file",
        help="Feature mat filename."
    )
    parser.add_argument(
        "score_file",
        help="Score Output mat filename."
    )
    # Optional arguments.
    # 由于设置了default,因此这些参数在命令行中是可选的
    parser.add_argument(
        "--model_def",
        default=os.path.join(
                "./models/market1501/caffenet/feature.proto"),
        help="Model definition file."
    )
    parser.add_argument(
        "--pretrained_model",
        default=os.path.join(
                "./models/market1501/caffenet/caffenet_iter_17000.caffemodel"),
        help="Trained model weights file."
    )
    parser.add_argument(
        "--gpu",
        type=int,
        default=-1,
        help="Switch for gpu computation."
    )
    parser.add_argument(
        //action='store_true'的意思是说,如果脚本有传递--center_only的参数则将该值center_only取值为true
        //由于脚本没有传递center_only,则其值为false
        "--center_only",
        action='store_true',
        help="Switch for prediction from center crop alone instead of " +
             "averaging predictions across crops (default)."
    )
    parser.add_argument(
        "--images_dim",
        default='256,256',
        help="Canonical 'height,width' dimensions of input images."
    )
    parser.add_argument(
        "--mean_value",
        default=os.path.join(
                             'examples/market1501/market1501_mean.binaryproto'),
        help="Data set image mean of [Channels x Height x Width] dimensions " +
             "(numpy array). Set to '' for no mean subtraction."
    )
    parser.add_argument(
        "--input_scale",
        type=float,
        help="Multiply input features by this scale to finish preprocessing."
    )
    parser.add_argument(
        "--raw_scale",
        type=float,
        default=255.0,
        help="Multiply raw input by this scale before preprocessing."
    )
    parser.add_argument(
        "--channel_swap",
        default='2,1,0',
        help="Order to permute input channels. The default converts " +
             "RGB -> BGR since BGR is the Caffe default by way of OpenCV."
    )
    parser.add_argument(
        "--ext",
        default='jpg',
        help="Image file extension to take as input when a directory " +
             "is given as the input file."
    )
    parser.add_argument(
        "--feature_name",
        default="fc7",
        help="feature blob name."
    )
    parser.add_argument(
        "--score_name",
        default="prediction",
        help="prediction score blob name."
    )
    args = parser.parse_args()

    //image_dims = [256,256]
    image_dims = [int(s) for s in args.images_dim.split(',')]

    channel_swap=[2,1,0]
    channel_swap = None
    if args.channel_swap:
        channel_swap = [int(s) for s in args.channel_swap.split(',')]

    mean_value= [97.8,99.0,105.6]
    mean_value = None
    if args.mean_value:
        mean_value = [float(s) for s in args.mean_value.split(',')]
        mean_value = np.array(mean_value)

    if args.gpu >= 0:
        caffe.set_mode_gpu()
        caffe.set_device(args.gpu)
        print("GPU mode, device : {}".format(args.gpu))
    else:
        caffe.set_mode_cpu()
        print("CPU mode")

    //这句话的意思是根据训练好的模型,使用dev.proto前向一遍,得到分类的结果
    //同时,前向网络也计算了fc7,这正是我们需要的特征
    --model_def = ./models/market1501/caffenet/dev.proto
    args.pretrained_model在命令行中存在
    input_scale为空,无默认值
    raw_scale=255
    channel_swap=[2,1,0]

    # Make classifier.
    classifier = SClassifier(args.model_def, args.pretrained_model,
            image_dims=image_dims, mean_value=mean_value,
            input_scale=args.input_scale, raw_scale=args.raw_scale,
            channel_swap=channel_swap)

    # Load numpy, directory glob (*.jpg), or image file.
    //将符号路径扩展成完整路径
    args.input_file = os.path.expanduser(args.input_file)
    //args.ext='jpg'
    //args.input_file以lst结尾
    if args.input_file.endswith(args.ext):
        print("Loading file: %s" % args.input_file)     
        inputs = [caffe.io.load_image(args.input_file)]
        labels = [-1]
    //lst也不是文件夹
    elif os.path.isdir(args.input_file):
        print("Loading folder: %s" % args.input_file)
        inputs =[caffe.io.load_image(im_f)
                 for im_f in glob.glob(args.input_file + '/*.' + args.ext)]
        labels = [-1 for _ in xrange(len(inputs))]
    else:
        ## Image List Files
        print("Loading file: %s" % args.input_file)
        //按列读取
        img_files, labels = load_txt(args.input_file)
        //对于lst中的每一个地址,就读取一次,放入到input中
        inputs = [caffe.io.load_image(im_f)
                  for im_f in img_files]

    print("Classifying %d inputs." % len(inputs))

    # Classify.
    ok = 0.0

    save_feature = None
    save_score   = None
    //由于脚本没有传递center_only,则其值为false
    for idx, _input in enumerate(inputs):
        start = time.time()
        //_input是每一张图,后面的参数说明是否要对图像进行crop
        //本例中是对图像进行了crop,四个角+一个中心,水平翻转之后再来一次,总计10张。否则我们仅仅需要中心的那张就可以
        //返回的是一张N*C的numpy.ndarry,代表每张图片有可能对应的C个类别
        _ = classifier.predict([_input], not args.center_only)
        //提取fc7层的特征
        feature = classifier.get_blob_data(args.feature_name)
        //获取使用softmax后的结果
        score   = classifier.get_blob_data(args.score_name)
        //都是一维的数据
        assert (feature.shape[0] == 1 and score.shape[0] == 1)
        feature_shape = feature.shape
        score_shape = score.shape
        //打印结果

        if save_feature is None:
            args.feature_name feature fc7 feature_shape(14096print('feature : {} : {}'.format(args.feature_name, feature_shape))
            save_feature = np.zeros((len(inputs), feature.size),dtype=np.float32)
        save_feature[idx, :] = feature.reshape(1, feature.size)
        if save_score is None:
            args.score_name score prediction (1,751)
            print('score : {} : {}'.format(args.score_name, score_shape))
            save_score = np.zeros((len(inputs), score.size),dtype=np.float32)
        save_score[idx, :] = score.reshape(1, score.size)
        //找到得分中最大的一项
        mx_idx = np.argmax(score.view())
        ok = ok + int(int(mx_idx) == int(labels[idx]))
        print("{:5d} / {:5d} images predict done in {:.2f} s. [PRED: {:3d}] vs [OK: {:3d}] accuracy: {:.4f} = good: {:5d} bad: {:5d}".format( \
                                      idx+1, len(inputs), time.time() - start, mx_idx, labels[idx], ok/(idx+1), int(ok), idx+1-int(ok)))


    # Save
    if (args.feature_file):
        print("Saving feature into %s" % args.feature_file)
        sio.savemat(args.feature_file, {'feature':save_feature})
    else:
        print("Without saving feature")

    if (args.score_file):
        print("Saving score into %s" % args.score_file)
        sio.savemat(args.score_file, {'feature':save_score})
    else:
        print("Without saving score")


if __name__ == '__main__':
    main(sys.argv)

这里写图片描述

你可能感兴趣的:(caffe,PersonReID)