1. 程式人生 > >caffe利用訓練好的模型進行實際測試

caffe利用訓練好的模型進行實際測試

官方版demo

import numpy as np
import os
import sys
import cv2
caffe_root = 'your caffe root'
sys.path.insert(0, caffe_root + '/python')
import caffe
caffe.set_device(1)
caffe.set_mode_gpu()
model_def = 'xxx_deploy.prototxt'
model_weights = 'xxx.caffemodel'
net = caffe.Net(model_def, model_weights, caffe.TEST)
net.blobs['data'
].reshape(1,3,h,w) # (batch_size,c,h,w) transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) transformer.set_transpose('data', (2,0,1)) # (h,w,c)--->(c,h,w) transformer.set_mean('data', np.array([104,117,123])) #注意是 BGR ''' 或者通過caffe_root/build/tools/compute_image_mean 計算影象均值得到xxx.npy mu = np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy') mu = mu.mean(1).mean(1) #對所有畫素值取平均以此獲取BGR的均值畫素值 print 'mean-subtracted values:', zip('BGR', mu) '''
transformer.set_raw_scale('data', 255) # rescale from [0, 1] to [0, 255] transformer.set_channel_swap('data', (2,1,0))# RGB--->BGR ''' 可能你對均值設定成BGR有疑問,不是到後面才把RGB轉為BGR嗎? 其實transformer.setXXX()這些只是設定屬性,實際執行順序是參考附錄preprocess函式定義 ''' image_names = [圖片list] for image_name in image_names: image = caffe.io.load_image(image_name)# 用的是skimage庫,見附錄
# 利用剛剛的設定進行圖片預處理 transformed_image = transformer.preprocess('data', image) net.blobs['data'].data[...] = transformed_image # 網路前傳(測試無後傳) output = net.forward() output_prob= output['prob'][0].argmax() # 概率最大的label print image_name,output_prob

自定義版(全部使用PIL)

訓練程式不動,只修改測試程式

import numpy as np
import os
import sys
from PIL import Image
caffe_root = 'your caffe root'
sys.path.insert(0, caffe_root + '/python')
import caffe
caffe.set_device(1)
caffe.set_mode_gpu()
model_def = 'xxx_deploy.prototxt'
model_weights = 'xxx.caffemodel'
net = caffe.Net(model_def, model_weights, caffe.TEST)

image_names = [圖片list]
for image_name in image_names:
    im = Image.open(image_name) 
    im = im.resize((w, h), Image.BILINEAR)
    im = np.array(im, dtype=np.float32) # im:(h,w,3) RGB
    im = im[:, :, ::-1] # im: (h,w,3) BGR
    im -= np.array((104, 117, 123)) # 減去均值,注意是 BGR
    im = im.transpose((2, 0, 1)) # im:(3,h,w)

    net.blobs['data'].reshape(1, *im.shape)
    net.blobs['data'].data[...] = im
    output = net.forward()
    output_prob= output['prob'][0].argmax()  # 概率最大的label
    print image_name,output_prob

自定義版(全部使用skimage)

### 宣告:未實際測試,謹慎使用
import skimage
from skimage import io,transform
#... 
in_db=lmdb.open('your data(images) lmdb path',map_size=int(1e12))
with in_db.begin(write=True) as in_txn:
    for in_idx,in_ in enumerate(file_list):         
        im_file='your images path'+in_
        im=io.imread(im_file,as_grey=False)
        im = transform.resize(im,(h, w),order=1)
        im = im * 255 # [0-1]->[0-255]
        im=im[:,:,::-1]#把im的RGB調整為BGR
        im_dat=caffe.io.array_to_datum(im)
        in_txn.put('{:0>10d}'.format(in_idx),im_dat.SerializeToString())   
        print 'data train: {} [{}/{}]'.format(in_, in_idx+1, len(file_list))        
        del im_file, im, im_dat
in_db.close()
print 'train data(images) are done!'

程式碼附錄:

# 都在caffe_root/python/caffe/io.py中定義
# 附錄preprocess函式定義
def preprocess(self, in_, data):
"""
        Format input for Caffe:
        - convert to single
        - resize to input dimensions (preserving number of channels)
        - transpose dimensions to K x H x W
        - reorder channels (for instance color to BGR)
        - scale raw input (e.g. from [0, 1] to [0, 255] for ImageNet models)
        - subtract mean
        - scale feature

        Parameters
        ----------
        in_ : name of input blob to preprocess for
        data : (H' x W' x K) ndarray

        Returns
        -------
        caffe_in : (K x H x W) ndarray for input to a Net
        """
   self.__check_input(in_)
        caffe_in = data.astype(np.float32, copy=False)
        transpose = self.transpose.get(in_)
        channel_swap = self.channel_swap.get(in_)
        raw_scale = self.raw_scale.get(in_)
        mean = self.mean.get(in_)
        input_scale = self.input_scale.get(in_)
        in_dims = self.inputs[in_][2:] # 初始化Transformer時傳入了
        #{'data': net.blobs['data'].data.shape} in_dims就是deploy的(h,w)
        # resize_image見附錄  shape[:2](h,w)-> in_dims
        if caffe_in.shape[:2] != in_dims:
            caffe_in = resize_image(caffe_in, in_dims) # 預設雙線性插值
        # (h,w,c)->(c,h,w)
        if transpose is not None:
            caffe_in = caffe_in.transpose(transpose)
        # RGB->BGR
        if channel_swap is not None:
            caffe_in = caffe_in[channel_swap, :, :]
        # [0-1]->[0-255]
        if raw_scale is not None:
            caffe_in *= raw_scale
        # 減去均值(BGR)
        if mean is not None:
            caffe_in -= mean
        if input_scale is not None:
            caffe_in *= input_scale
        return caffe_in
# 附錄caffe.io.load_image函式定義
def load_image(filename, color=True):
    """
    Load an image converting from grayscale or alpha as needed.

    Parameters
    ----------
    filename : string
    color : boolean
        flag for color format. True (default) loads as RGB while False
        loads as intensity (if image is already grayscale).

    Returns
    -------
    image : an image with type np.float32 in range [0, 1]
        of size (H x W x 3) in RGB or
        of size (H x W x 1) in grayscale.
    """
   ############注意skimage###############
    img = skimage.img_as_float(skimage.io.imread(filename, as_grey=not color)).astype(np.float32) # 轉為float32
    if img.ndim == 2: # 灰度圖 int gray = 0.3*red + 0.59*green + 0.11*blue;
    # 改進版int gray = (77*red + 150*green + 29*blue + 128) >> 8;
        img = img[:, :, np.newaxis] # (h,w)->(h,w,1)
        if color:
            img = np.tile(img, (1, 1, 3)) # (h,w,1)->(h,w,3)把灰度重複一下
    elif img.shape[2] == 4: # shape:(h,w,c) 即c = 4 png4個通道 alpha透明值
        img = img[:, :, :3] # 只取0,1,2這三個通道
    return img
# 附錄resize_image函式定義
def resize_image(im, new_dims, interp_order=1):
    """
    Resize an image array with interpolation.

    Parameters
    ----------
    im : (H x W x K) ndarray
    new_dims : (height, width) tuple of new dimensions.
    interp_order : interpolation order, default is linear.雙線性
    參考上篇部落格中interp_order的設定

    Returns
    -------
    im : resized ndarray with shape (new_dims[0], new_dims[1], K)
    """
    # 灰度圖或者RGB三通道圖
    if im.shape[-1] == 1 or im.shape[-1] == 3:
        im_min, im_max = im.min(), im.max()
        if im_max > im_min:
            # skimage is fast but only understands {1,3} channel images
            # in [0, 1].
            im_std = (im - im_min) / (im_max - im_min)
            resized_std = resize(im_std, new_dims, order=interp_order)
            # 檔案開頭有from skimage.transform import resize 就是skimage中的resize函式
            resized_im = resized_std * (im_max - im_min) + im_min
        else:
            # the image is a constant -- avoid divide by 0
            ret = np.empty((new_dims[0], new_dims[1], im.shape[-1]),
                           dtype=np.float32)
            ret.fill(im_min)
            return ret
    else:
        # ndimage interpolates anything but more slowly.
        scale = tuple(np.array(new_dims, dtype=float) / np.array(im.shape[:2]))
        resized_im = zoom(im, scale + (1,), order=interp_order)
    return resized_im.astype(np.float32)