cnn_caffe.py 5.34 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
    Runs ImageNet Convolutional Neural Network implemented in software Caffe.
    This module only implements the classification. The network must be trained previously using caffe.
    
    Krizhevsky, Alex, Ilya Sutskever, and Geoffrey E. Hinton, Imagenet classification with deep convolutional neural networks, Advances in neural information processing systems, 2012.
    Jia, Yangqing and Shelhamer, Evan and Donahue, Jeff and Karayev, Sergey and Long, Jonathan and Girshick, Ross and Guadarrama, Sergio and Darrell, Trevor, Caffe: Convolutional Architecture for Fast Feature Embedding, arXiv preprint arXiv:1408.5093, 2014.
    
    Name: cnn_caffe.py
    Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
"""

# Make sure that caffe is on the python path:
caffe_root = '/var/tmp/caffe/' 
import sys
sys.path.insert(0, caffe_root + 'python')
import caffe

import cv2
import numpy as np
import os

from collections import OrderedDict

from util.config import Config
from util.file_utils import File
from util.utils import TimeUtils

from classifier import Classifier

class CNNCaffe(Classifier):

    def __init__(self):
        self._create_net()
        
    def _create_net(self):
        self.model_def = Config("ModelDef", caffe_root + 'models/bvlc_reference_caffenet/deploy.prototxt', str)
        self.model_weights = Config("ModelWeights", caffe_root + 'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel', str)
                       
        self.net = caffe.Net(self.model_def.value,          # defines the structure of the model
                                self.model_weights.value,   # contains the trained weights
                                caffe.TEST)                 # use test mode (e.g., don't perform dropout)
        
        self.mean_image = Config("MeanImage", caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy', str)
        # load the mean image for subtraction
        mu = np.load(self.mean_image.value)
        mu = mu.mean(1).mean(1)  # average over pixels to obtain the mean (BGR) pixel values

        # create transformer for the input called 'data'
        self.transformer = caffe.io.Transformer({'data': self.net.blobs['data'].data.shape})

        self.transformer.set_transpose('data', (2,0,1))  # move image channels to outermost dimension
        self.transformer.set_mean('data', mu)            # subtract the dataset-mean value in each channel
        self.transformer.set_raw_scale('data', 255)      # rescale from [0, 1] to [0, 255]
        self.transformer.set_channel_swap('data', (2,1,0))  # swap channels from RGB to BGR

        self.labels_file = Config("LabelsFile", caffe_root + 'data/ilsvrc12/synset_words.txt', str)
    
    def get_config(self):
        caffe_config = OrderedDict()
        
        caffe_config["model_def"] = self.model_def
        caffe_config["model_weights"] = self.model_weights
        caffe_config["mean_image"] = self.mean_image
        caffe_config["labels_file"] = self.labels_file
        
        return caffe_config
        
    def set_config(self, configs):
        self.model_def = Config.nvl_config(configs["model_def"], self.model_def)
        self.model_weights = Config.nvl_config(configs["model_weights"], self.model_weights)
        self.mean_image = Config.nvl_config(configs["mean_image"], self.mean_image)
        self.labels_file = Config.nvl_config(configs["labels_file"], self.labels_file)
        
        self._create_net()

    def get_summary_config(self):
        caffe_config = OrderedDict()
        
        caffe_config[self.model_def.label] = self.model_def.value
        caffe_config[self.model_weights.label] = self.model_weights.value
        caffe_config[self.mean_image.label] = self.mean_image.value
        caffe_config[self.labels_file.label] = self.labels_file.value

        summary = ''
        for config in caffe_config:
            summary += "%s: %s\n" % (config, str(caffe_config[config]))
        
        return summary

    
    def classify(self, dataset, test_dir, test_data):
        test_dir = File.make_path(dataset, test_dir)
            
        classes = []
        labels = np.loadtxt(self.labels_file.value, str)

        images = sorted(os.listdir(File.make_path(test_dir)))

        for image in images:
            filepath = File.make_path(test_dir, image)
            image = cv2.imread(filepath)
                
            # resize the segment
            resized_image = np.zeros((512, 512, image.shape[2]), dtype="uint8")
            resized_image[0:image.shape[0], 0:image.shape[1]] = image[:,:]
            resized_image = resized_image[0:256, 0:256]
            cv2.imwrite(filepath.replace('.tif', '.jpeg'), resized_image)
            
            # load the image
            input_image = caffe.io.load_image(filepath)
            transformed_image = self.transformer.preprocess('data', input_image)
            
            # copy the image data into the memory allocated for the net
            self.net.blobs['data'].data[...] = transformed_image

            # perform classification
            output = self.net.forward()
            
            # the output probability vector for the first image in the batch
            prediction = output['prob'][0] 
            print(["%0.4f" % pr for pr in prediction ])

            classes.append(labels[prediction.argmax()])

        return classes