Preface

Caffe is a commonly used deep learning framework. Unlike some other mainstream frameworks that can be installed directly via pip, Caffe is more commonly installed through compilation. Therefore, this article is written to document the installation process.

Installing Caffe on Ubuntu

For Ubuntu versions >= 17.04, you can install the Python 3 version of Caffe using the following command:

apt install caffe-cpu

For versions lower than 17.04, source code compilation is required. The author’s system is 64-bit Ubuntu 16.04, and the following installation steps (using Python 2) are described:

Installing Dependencies

First, install the necessary dependencies. It is important to ensure all are installed to avoid compilation errors. Re-running these commands if dependencies are already installed will not cause issues:

apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compiler
apt-get install --no-install-recommends libboost-all-dev  
apt-get install libgflags-dev libgoogle-glog-dev liblmdb-dev
apt-get install libatlas-base-dev
apt-get install python-numpy
apt-get install libhdf5-serial-dev
apt-get install python-dev
apt install python-pip
pip install scikit-image

Modifying Compilation Configuration

Since we will compile from source, first clone the Caffe repository and copy the official configuration example:

# Switch to the /opt directory
cd /opt
# Clone the Caffe source code
git clone git://github.com/BVLC/caffe.git
# Enter the source code root directory
cd caffe/
# Copy the official compilation configuration example
cp Makefile.config.example Makefile.config
# Edit the configuration file
vim Makefile.config

Modify the configuration file as follows:

  • Uncomment line 8 to compile the CPU version of Caffe:
CPU_ONLY := 1
  • Then modify lines 96-98 to:
# Whatever else you find you need goes here.
INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include /usr/include/hdf5/serial
LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu/hdf5/serial

Starting Compilation

Now you can start compiling. The first two commands compile the source code and Python interface, while the last two compile tests. -j4 uses 4 threads for parallel compilation to speed up the process:

make -j4 pycaffe
make -j4 all
make -j4 test
make -j4 runtest

Adding Environment Variables

Use the command vim /etc/profile to add the following line at the end of the file:

export PYTHONPATH=/opt/caffe/python:$PYTHONPATH

Test the installation to verify success. A successful installation will output the Caffe version information:

# python
Python 2.7.12 (default, Dec  4 2017, 14:50:18)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import caffe
>>> caffe.__version__

Expected output:

'1.0.0'

Using a Model to Predict Images

After installing Caffe, you can use a pre-trained model to predict images. The author downloaded the model from here, using the MobileNet V2 model in the following example:

# coding=utf-8
from __future__ import print_function
import numpy as np
import caffe

# Resize image to meet model requirements
def get_img(img_path, nh, nw):
    im = caffe.io.load_image(img_path)
    h, w, _ = im.shape
    if h < w:
        off = (w - h) / 2
        im = im[:, off:off + h]
    else:
        off = (h - w) / 2
        im = im[off:off + h, :]
    im = caffe.io.resize_image(im, [nh, nw])
    return im

def eval(image_path, nh, nw):
    caffe.set_mode_cpu()
    # Load the model
    net = caffe.Net("mobilenet_v2_deploy.prototxt", "mobilenet_v2.caffemodel", caffe.TEST)

    # Set image preprocessing parameters
    transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
    transformer.set_transpose('data', (2, 0, 1))  # Channel last to first
    transformer.set_channel_swap('data', (2, 1, 0))  # RGB to BGR
    transformer.set_raw_scale('data', 255)  # Convert [0,1] to [0,255]
    # Subtract image mean
    img_mean = np.array([103.94, 116.78, 123.68], dtype=np.float32)
    transformer.set_mean('data', img_mean)
    # Scale input
    transformer.set_input_scale('data', 0.017)
    # Reshape the data blob to match input dimensions
    net.blobs['data'].reshape(1, 3, nh, nw)

    im = get_img(image_path, nh, nw)
    net.blobs['data'].data[...] = transformer.preprocess('data', im)
    out = net.forward()
    # Get prediction results
    prob = out['prob']
    prob = np.squeeze(prob)
    idx = np.argsort(-prob)
    # Get the top label
    label = idx[0]
    # Load label names
    label_names = np.loadtxt('synset.txt', str, delimiter='\t')
    print('%.5f - %s' % (prob[label], label_names[label]))

if __name__ == '__main__':
    image_path = "cat.jpg"
    nh, nw = 224, 224
    eval(image_path, nh, nw)

Explanation of Key Functions:

  1. Image Resizing Function: Adjusts image dimensions to fit the model’s input requirements. Note: For Python 3, use // instead of / for integer division.
def get_img(img_path, nh, nw):
    im = caffe.io.load_image(img_path)
    h, w, _ = im.shape
    if h < w:
        off = (w - h) / 2
        im = im[:, off:off + h]
    else:
        off = (h - w) / 2
        im = im[off:off + h, :]
    im = caffe.io.resize_image(im, [nh, nw])
    return im
  1. Model and Configuration Loading: Specifies CPU mode and loads the deployment configuration file and model weights:
caffe.set_mode_cpu()
net = caffe.Net("mobilenet_v2_deploy.prototxt", "mobilenet_v2.caffemodel", caffe.TEST)
  1. Image Preprocessing: Configures channel order, scaling, mean subtraction, etc.:
transformer.set_transpose('data', (2, 0, 1))  # RGB to BGR channel order
transformer.set_channel_swap('data', (2, 1, 0))
transformer.set_raw_scale('data', 255)
transformer.set_mean('data', img_mean)
transformer.set_input_scale('data', 0.017)
  1. Prediction Execution: Processes the image, runs inference, and outputs the top prediction result:
im = get_img(image_path, nh, nw)
net.blobs['data'].data[...] = transformer.preprocess('data', im)
out = net.forward()
prob = out['prob']
prob = np.squeeze(prob)
idx = np.argsort(-prob)
label = idx[0]
label_names = np.loadtxt('synset.txt', str, delimiter='\t')
print('%.5f - %s' % (prob[label], label_names[label]))

Expected Output:

0.25784 - 'n02123159 tiger cat'

References

  1. http://caffe.berkeleyvision.org/installation.html
  2. https://blog.csdn.net/qq_25737169/article/details/77773884
  3. https://github.com/shicai/MobileNet-Caffe
Xiaoye