Commit 5743c24c authored by Alessandro dos Santos Ferreira's avatar Alessandro dos Santos Ferreira
Browse files

Pynovisao - Modificacoes no CNN Caffe

parent 50d4bafd
...@@ -31,33 +31,32 @@ from util.utils import TimeUtils ...@@ -31,33 +31,32 @@ from util.utils import TimeUtils
from classifier import Classifier from classifier import Classifier
class CNNCaffe(Classifier): class CNNCaffe(Classifier):
CREATE_LMDB = False
def __init__(self): def __init__(self):
self._create_net() self._create_net()
def _create_net(self): def _create_net(self):
self.model_def = Config("ModelDef", caffe_root + 'models/bvlc_reference_caffenet/deploy.prototxt', str) self.model_def = Config("ModelDef", '../examples/deploy.prototxt', str)
self.model_weights = Config("ModelWeights", caffe_root + 'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel', str) self.model_weights = Config("ModelWeights", '../examples/caffenet_train_iter_3000.caffemodel', str)
self.net = caffe.Net(self.model_def.value, # defines the structure of the model self.net = caffe.Net(self.model_def.value, # defines the structure of the model
self.model_weights.value, # contains the trained weights self.model_weights.value, # contains the trained weights
caffe.TEST) # use test mode (e.g., don't perform dropout) 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' # create transformer for the input called 'data'
self.transformer = caffe.io.Transformer({'data': self.net.blobs['data'].data.shape}) 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_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_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.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) self.mean_image = Config("MeanImage", '../examples/imagenet_mean.binaryproto', str)
self.labels_file = Config("LabelsFile", '../examples/labels.txt', str)
def get_config(self): def get_config(self):
caffe_config = OrderedDict() caffe_config = OrderedDict()
...@@ -92,15 +91,34 @@ class CNNCaffe(Classifier): ...@@ -92,15 +91,34 @@ class CNNCaffe(Classifier):
def classify(self, dataset, test_dir, test_data): def classify(self, dataset, test_dir, test_data):
if CNNCaffe.CREATE_LMDB:
return self._classify_lmdb(dataset, test_dir, test_data)
test_dir = File.make_path(dataset, test_dir) test_dir = File.make_path(dataset, test_dir)
classes = [] classes = []
labels = np.loadtxt(self.labels_file.value, str) labels = np.loadtxt(self.labels_file.value, str)
images = sorted(os.listdir(File.make_path(test_dir))) images = sorted(os.listdir(File.make_path(test_dir)))
# convert mean.binaryproto to mean.npy
blob = caffe.proto.caffe_pb2.BlobProto()
data = open( self.mean_image.value, 'rb' ).read()
blob.ParseFromString(data)
np.save( File.make_path(test_dir, 'mean.npy'), np.array( caffe.io.blobproto_to_array(blob) )[0] )
# load the mean image for subtraction
mu = np.load( File.make_path(test_dir, 'mean.npy') )
mu = mu.mean(1).mean(1) # average over pixels to obtain the mean (BGR) pixel values
self.transformer.set_mean('data', mu) # subtract the dataset-mean value in each channel
self.net.blobs['data'].reshape(1, # batch size
3, # 3-channel (BGR) images
227, 227) # image size is 227x227
for image in images: for im in images:
filepath = File.make_path(test_dir, image) filepath = File.make_path(test_dir, im)
image = cv2.imread(filepath) image = cv2.imread(filepath)
# resize the segment # resize the segment
...@@ -114,7 +132,7 @@ class CNNCaffe(Classifier): ...@@ -114,7 +132,7 @@ class CNNCaffe(Classifier):
transformed_image = self.transformer.preprocess('data', input_image) transformed_image = self.transformer.preprocess('data', input_image)
# copy the image data into the memory allocated for the net # copy the image data into the memory allocated for the net
self.net.blobs['data'].data[...] = transformed_image self.net.blobs['data'].data[...] = [transformed_image]
# perform classification # perform classification
output = self.net.forward() output = self.net.forward()
...@@ -126,3 +144,83 @@ class CNNCaffe(Classifier): ...@@ -126,3 +144,83 @@ class CNNCaffe(Classifier):
classes.append(labels[prediction.argmax()]) classes.append(labels[prediction.argmax()])
return classes return classes
def _classify_lmdb(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)))
# create LMDB listfile
listfile = open(File.make_path(test_dir, 'listfile.txt'), 'w')
for im in images:
filepath = File.make_path(test_dir, im)
image = cv2.imread(filepath)
# resize the segment and save in jpeg format
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)
# append imagename in listfile
listfile.write("%s %d\n" %(im.replace('.tif', '.jpeg'), 0))
listfile.close()
# create LMDB backend to be used as source of data
from subprocess import call
call([caffe_root + 'build/tools/convert_imageset',
File.make_path(test_dir, ''),
File.make_path(test_dir, 'listfile.txt'),
File.make_path(test_dir, 'lmdb')])
# read model_def
with open(self.model_def.value, 'r') as model_def:
prototxt = model_def.read()
# change structure of layer data
layers = prototxt.split('layer')
layers[1] = (' {\n'
' name: "data"\n'
' type: "Data"\n'
' top: "data"\n'
' top: "label"\n'
' transform_param {\n'
' mirror: false\n'
' crop_size: 227\n'
' mean_file: "' + self.mean_image.value + '"\n'
' }\n'
' data_param {\n'
' source: "' + File.make_path(test_dir, 'lmdb') + '"\n'
' batch_size: 1\n'
' backend: LMDB\n'
' }\n'
'}\n')
prototxt = 'layer'.join(layers)
# create new model_def
new_model_def_path = File.make_path(test_dir, 'deploy.prototxt')
with open(new_model_def_path, 'w') as new_model_def:
new_model_def.write(prototxt)
net = caffe.Net(new_model_def_path, # 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)
for im in images:
# perform classification
output = 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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment