Caffe实战(十一):caffe单个图像分类测试的方法总结

 
对于训练好的模型,通常需要输入一些其它图像进行测试,用来判断训练好的模型的准确率。由于是单幅图像,或者少数图像的分类测试,转换为lmdb或leveldb格式,再利用caffe工具进行测试比较麻烦。这里总结一些测试图像分类结果的方法,方便今后使用。
 

方法一:利用caffe自带的classification工具(C++)

 
caffe中自带图像分类工具classfication.exe,对输入一张图片,输出分类结果。源码在caffe\examples\cpp_classification\classification.cpp
rem 分类工具
rem 参数(1)网络模型定义文件
rem 参数(2)权值文件
rem 参数(3)均值文件
rem 参数(4)同义词词集文件(标签类别)
rem 参数(5)输入图像
 
..\\..\\Build\\x64\\Release\\classification.exe  ..\\..\\models\\bvlc_reference_caffenet\\deploy.prototxt  ..\\..\\models\\bvlc_reference_caffenet\\bvlc_reference_caffenet.caffemodel ..\\..\\data\\ilsvrc12\\imagenet_mean.binaryproto ..\\..\\data\\ilsvrc12\\synset_words.txt ..\\..\\examples\\images\\cat.jpg

 

分类结果如下所示:
 
 

方法二:利用caffe自带的classify.py工具(python)

 
caffe开发团队实际上也编写了一个python版本的分类文件,路径为 python/classify.py
 
运行这个文件必需两个参数,一个输入图片文件,一个输出结果文件。分类的结果保存为当前目录下的xxx.npy文件里面,是看不见的。而且这个文件有错误,运行的时候,会提示“Mean shape incompatible with input shape”的错误。因此,要使用这个文件,我们还得进行修改:
 
(1)修改均值计算:
定位到
mean = np.load(args.mean_file)
这一行,在下面加上一行:
mean=mean.mean(1).mean(1)
则可以解决报错的问题。
 
2)修改文件,使得结果显示出来:
定位到
# Classify.
    start = time.time()
    predictions = classifier.predict(inputs, not args.center_only)
    print("Done in %.2f s." % (time.time() - start))
这个地方,在后面加上几行,如下所示:
  # Classify.
    start = time.time()
    predictions = classifier.predict(inputs, not args.center_only)
    print("Done in %.2f s." % (time.time() - start))
 
    imagenet_labels_filename = '../data/ilsvrc12/synset_words.txt'
    labels = np.loadtxt(imagenet_labels_filename, str, delimiter='\t')
    top_k = predictions.flatten().argsort()[-1:-6:-1]
    for i in np.arange(top_k.size):
        print top_k[i], labels[top_k[i]]
 
修改完成之后,调用指令:
rem 测试ilsvrc12训练后的分类结果
rem 参数(1)--model_def     模型文件
rem 参数(2)--pretrained_model 训练权值参数
rem 参数(3)--center_only   中心裁剪(可能??)
 
rem 参数(4cat.jpg         输入图像
rem 参数(5)foo             测试结果存放文件
 
cd E:
cd E:\Learning\caffe\Microsoft\caffe
 
python2 tools-my\\classify_python\\classify_ilsvrc12.py --model_def models/bvlc_reference_caffenet/deploy.prototxt --pretrained_model models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel --mean_file data/ilsvrc12/ilsvrc_2012_mean.npy --center_only examples/images/cat.jpg tools-my\\classify_python\\result.npy

 

测试结果如下:
 
特别注意:这里使用的是ilsvrc_2012_mean.npy均值文件(caffe/python中自带的),可以通过“ numpy.load(args.mean_file)”加载该文件;不能使用caffe自带的计算均值工具“compute_image_mean.exe”输出的“imagenet_mean.binaryproto”文件。否则,会提示“ValueError: Object arrays cannot be loaded when allow_pickle=False”之类的错误。
 
因此,在进行cifar10测试过程中,由于使用的是“mean.binaryproto”文件,利用“ numpy.load(args.mean_file)”加载总是失败(不符合类型要求),需要修改成cifar_mean.npy格式的均值文件或者修改相应的python代码使之能够加载二进制文件。(Python还不是很熟,有时间了研究下)
 
将mean.binaryproto转换为mean.npy过程如下所示:
# 编写一个函数,将二进制的均值转换为Python的均值
def convert_mean(binMean, npyMean):
    blob = caffe.proto.caffe_pb2.BlobProto() # 声明一个blob
    bin_mean = open(binMean,'rb').read() # 打开二进制均值文件
    blob.ParseFromString(bin_mean)  # 将二进制均值文件读入blob
    arr = np.array(caffe.io.blobproto_to_array(blob)) # 将blob转换为numpy array
    npy_mean = arr[0]
    print arr.shape # arr是四维array,第一维表示第一图,其实就是唯一一张均值图
    np.save(npyMean, npy_mean)
 
binMean = caffe_root + 'data\\cifar10\\mean.binaryproto'
npyMean = caffe_root + 'data\\cifar10\\mean.npy'
convert_mean(binMean, npyMean)

 

(3)改进显示结果
 
上面的方式存在不足之处:
  • 标签文件的路径写死在代码中;
  • 只显示的分类的结果,没有显示对应的分类概率值。
 
【添加pandas库】
import pandas as pd
 
【增加命令行参数】
将标签文件路径作为参数传入进来,定义为"--labels_file";另外,添加参数"--print_results"用来选择是否显示结果信息。
    parser.add_argument(
        "--print_results",
        action='store_true',
        help="show classify result."
    )
    parser.add_argument(
        "--labels_file",
        default='data/ilsvrc12/synset_words.txt',
        help="labels file."
    )
 
【添加显示结果信息】
# show classify result by caisenchuan 2019.11.21
    # define --print_results and  --labels_file.
    if args.print_results:
        scores = predictions.flatten()
        with open(args.labels_file) as f:
            labels_df = pd.DataFrame([
                    {
                        'synset_id': l.strip().split(' ')[0],
                        'name': ' '.join(l.strip().split(' ')[1:]).split(',')[0]
                    }
                    for l in f.readlines()
                ])
            labels = labels_df.sort_values('synset_id')['name'].values
            
            indices = (-scores).argsort()[:5]
            ps = labels[indices]
            
            meta = [
                ( p, '%.5f' % scores[i])
                for i,p in zip(indices, ps)
            ]
            
            print(meta)

 

调用方式:
rem 测试ilsvrc12训练后的分类结果
rem 参数(1)--model_def     模型文件
rem 参数(2)--pretrained_model 训练权值参数
rem 参数(3)--center_only   中心裁剪(可能??)
rem 参数(4)--print_results 打印分类结果信息  (自定义)
rem 参数(5)--labels_file   标签文件 (自定义)
 
rem 参数(6cat.jpg         输入图像
rem 参数(7)foo             测试结果存放文件
 
cd E:
cd E:\Learning\caffe\Microsoft\caffe
 
python2 tools-my\\classify_python\\classify.py --model_def models/bvlc_reference_caffenet/deploy.prototxt --pretrained_model models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel --mean_file data/ilsvrc12/ilsvrc_2012_mean.npy --center_only --print_results --labels_file data\\ilsvrc12\\synset_words.txt examples\\images\\cat.jpg tools-my\\classify_python\\result.npy

 

显示结果如下:
 
注意:synset_words.txt需要在类别名称前加上标号,而且千万注意最后一行不能为空,如下所示:
0 airplane
1 automobile
2 bird
3 cat
4 deer
5 dog
6 frog
7 horse
8 ship
9 truck
后期可以进一步修改,输出类似classfication.exe工具结果样式。

方法三:python方法(网上的测试样例)

 
#coding=utf-8
 
import numpy as np
import sys,os
 
# 设置caffe根目录
caffe_root = 'E:\\Learning\\caffe\\Microsoft\\caffe\\'
print(sys.path)
sys.path.insert(0,caffe_root + 'Build\x64\Release\pycaffe')
 
import caffe
os.chdir(caffe_root)
 
# 网络模型与权值文件路径
net_file = caffe_root +  'models\\bvlc_reference_caffenet\\deploy.prototxt'
caffe_model = caffe_root +  'models\\bvlc_reference_caffenet\\bvlc_reference_caffenet.caffemodel'
mean_file = caffe_root +  'data\\ilsvrc12\\ilsvrc_2012_mean.npy'
 
# 初始化网络以及Transformer
net = caffe.Net(net_file, caffe_model, caffe.TEST)
transformer =  caffe.io.Transformer({'data':net.blobs['data'].data.shape})
transformer.set_transpose('data',(2,0,1))
transformer.set_mean('data',np.load(mean_file).mean(1).mean(1))
transformer.set_raw_scale('data',255)
transformer.set_channel_swap('data',(2,1,0))
 
# 加载测试图像,正向传播
im = caffe.io.load_image(caffe_root +  'examples\\images\\cat.jpg')
net.blobs['data'].data[...] =  transformer.preprocess('data',im)
out = net.forward()
 
# 加载类别标签文件
imagenet_labels_filename = caffe_root +  'data\\ilsvrc12\\synset_words.txt'
labels = np.loadtxt(imagenet_labels_filename, str, delimiter  = '\t')
 
# 输出概率最大的前5组分类结果
top_k =  net.blobs['prob'].data[0].flatten().argsort()[-1:-6:-1]
for i in np.arange(top_k.size):
    print top_k[i], labels[top_k[i]]

 

参考: 【Caffe实战】caffe各接口对输入图像通道顺序的处理
 

posted on 2021-08-10 18:32  悬崖边上打坐  阅读(319)  评论(0编辑  收藏  举报

导航