在测试时,imagedata层有时候需要一些不支持的功能,需要修改底层文件,麻烦,后面直接调pycaffe完成。
调用caffe测试时,prototxt文件还需要保留imagedata层,本文中,prototxt文件输入如下
name: 'cls-v3'
input_name:'data'
input_shape{
dims:1
dims:3
dims:16
dims:16
}
导入pycaffe,读取模型。
# -*- coding: utf-8 -*-
#encoding: utf-8
import sys
import cv2
import numpy as np
import os
from PIL import Image
import io
#引入pycaffe 用于测试
caffe_path = r'caffe/python/'
sys.path.insert(0, caffe_path)
import caffe
caffe_proto_path = "model.prototxt"
caffe_model_path = "model.caffemodel"
#设置GPU
#caffe.set_mode_cpu()
caffe.set_mode_gpu()
caffe.set_device(0)
#前向测试
net = caffe.Net(caffe_proto_path, caffe_model_path, caffe.TEST)
输入数据预处理
# 设定图片的shape格式为网络data层格式
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
# 改变维度的顺序,由原始图片维度(width, height, channel)变为(channel, width, height)
transformer.set_transpose('data', (2,0,1))
# 减去均值,注意要先将binaryproto格式均值文件转换为npy格式[此步根据训练model时设置可选]
transformer.set_mean('data', np.array([0.406, 0.456, 0.485])) # [103.53,116.28,123.675])
transformer.set_input_scale('data', 1.0)
# transformer.set_input_scale('data', 0.00392156862745)
# transformer.set_mean('data', np.load(mean_file_path).mean(1).mean(1))
#caffe.io.load_image()读入的像素值是[0-1]之间,且通道顺序为RGB,而caffe内部的数据格式是BGR,因此需要进行如下操作,
#若是使用opencv打开图片,则无需进行如下操作。
# 缩放到[0,255]之间,根据模型输入需要是否开启
# transformer.set_raw_scale('data', 255)
# 交换通道,将图片由RGB变为BGR
transformer.set_channel_swap('data', (2,1,0))
前向读取结果
将加载的图片送入模型,保存前向结果
test_file_path = 'image_list.txt'
save_result = io.open('model_precision.txt', mode='w+', encoding ='utf-8')
test_image_list = io.open(test_file_path, mode='r',encoding ='utf-8')
lines1 = test_image_list.readlines()
img_list = list()
name_list=list()
for line1 in lines1:
image_path = line1.split(' ')[0]
# 加载图片
img = caffe.io.load_image(image_path)
current_num +=1
if current_num % batch_num != 0:
img_list.append(transformer.preprocess('data', img))
name_list.append(image_path)
else:
img_list.append(transformer.preprocess('data', img))
name_list.append(image_path)
net.blobs['data'].data[...] = img_list
net.forward()
for j in range(batch_num):
out_result_part = name_list[j]
out_prob = output['prob'][0]# prob vector
label = out_prob.argmax()#输出最大概率的那一类
prob = out_prob[label]# the prob value correspoding to the predict catogory
print(out_result_part, label, prob)
# 保存所有结果 置信度
for i in net.blobs['prob'].data[j, :, 0, 0]:
out_result_part += ' ' + str(i)
save_result.write(u'{}\n'.format(out_result_part))
a = list()
name_list = list()
print(num, current_num)
加载图片方式
cv2.imread() :BGR 0-255
如果用cv2.imread()接口读图像,读进来直接是BGR 格式and 0~255
所以不需要再缩放到【0,255】和通道变换【2,1,0】
不需要transformer.set_raw_scale(‘data’,255)和transformer.set_channel_swap(‘data’,(2,1,0)
caffe.io.load_image():RGB float 0-1
若是caffe.io.load_image()读进来是RGB格式和0~1(float)
所以在进行特征提取之前要在transformer中设置transformer.set_raw_scale(‘data’,255)(缩放至0~255)
以及transformer.set_channel_swap(‘data’,(2,1,0)(将RGB变换到BGR)
skimage.io.imread():unit8 0-255
skimage.io.imread得到的是uint8的数据,实际使用时需要注意格式转换!
#读取图片
img=skimage.io.imread(img_path), uint8,0-255
img=caffe.io.load_image(img_path), float,0-1
# 值转换到255
img=skimage.io.imread(img_path),uint8,0-255
img=caffe.io.load_image(img_path)*255,float,0-255
#减均值
img1=skimage.io.imread(img_path)-mean,uint8,0-255
img2=caffe.io.load_image(img_path)*255-mean,float,0-255
# 如果均值为int型,img1有可能依然是int8类型,导致很多数值变为0,结果全部错误。---这个导致无论输入什么,输出类别和置信度等都是一模一样。
#此时看似没什么问题。但是第一种方式,减掉均值后,很多地方变成0了。这个在对整图操作时,可能影响还不大,但是如果你要考虑局部的信息,比如像素点的局部信息,此时你就等着吧,绝对因为大部分是0,什么都没有了。
# 而第二种情况,因为是浮点数,减均值后还是有值的,在0附近的小数,于是这个还是比较正常的输入值,对DL来说,当你定位到局部信息时,还是比较真实的。
#正确方式
img=(skimage.io.imread(img_path))*1.0,uint8,0-255
img=caffe.io.load_image(img_path)*255,float,0-255
读入的为int格式,需要转为float格式,否则会导致结果都为0。
使用PIL来读取图片
对于彩色图像,不管其图像格式是PNG,还是BMP,或者JPG,在PIL中,使用Image模块的open()函数打开后,返回的图像对象的模式都是“RGB”。而对于灰度图像,不管其图像格式是PNG,还是BMP,或者JPG,打开后,其模式为“L”。所以需要转换格式,但不需要缩放到[0,255]
data = np.array(Image.open(self.dataRoot+img_list))
data = np.transpose(data,(2,0,1))#转换通道
data[[0,2],...] = data[[2,0],...] #RGB→BGR
参考文章:
https://lavi-liu.blog.csdn.net/article/details/80171494
https://blog.csdn.net/smf0504/article/details/60138863