Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

dnn: classify with mean substraction, results different for caffe and opencv

This question is strongly connected to: http://answers.opencv.org/question/178680/how-to-use-meanbinaryproto-with-blobfromimages/

I'm working with OpenCV 3.4.1 and caffe 1.0.0

I have different results for classification in caffe and OpenCV only when I'm using mean subtraction, without it everything works fine. I have the same observation for some caffenet and squeezenet_v1.1 models. My code:

import cv2
import caffe
import numpy as np

#  function comparing results of image classification in opencv and caffe:
#  with mean substraction results don't match
def caffe_vs_ocv_with_mean_subs(caffemodel, deploy_prototxt):
    #  read mean
    blob = caffe.proto.caffe_pb2.BlobProto()
    with open("mean.binaryproto", 'rb') as f:
        blob.ParseFromString(f.read())
        data = np.array(blob.data).reshape([blob.channels, blob.height, blob.width])
        cv_mean = [np.mean(data[0]), np.mean(data[1]), np.mean(data[2])]

    # define caffe net
    net = caffe.Net(deploy_prototxt, caffemodel, caffe.TEST)
    transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
    transformer.set_mean('data', data)
    transformer.set_transpose('data', (2, 0, 1))

    # get caffe prediction
    img = cv2.imread("example.jpg")
    img = cv2.resize(img, (227, 227), cv2.INTER_LINEAR)
    net.blobs['data'].data[...] = transformer.preprocess('data', img)
    out = net.forward()
    print "mean: " + str(cv_mean)
    print "caffe probs: " + str(out['prob'][0])

    # define openCv net
    cv_net = cv2.dnn.readNetFromCaffe(deploy_prototxt, caffemodel)
    # get opencv predictions:
    img_for_cv = cv2.imread("example.jpg")
    #  swapRB=False, just like in http://answers.opencv.org/question/178680/how-to-use-meanbinaryproto-with-blobfromimages/,
    #  but I tried any combinations of swapRB, crop flags
    cv_blob = cv2.dnn.blobFromImage(img_for_cv, 1, (227,227), cv_mean, swapRB=False, crop=False)
    cv_net.setInput(cv_blob)
    prob = cv_net.forward()
    print "cv probs" + str(prob)


#  no mean substrucation - this works fine
def caffe_vs_ocv_simple(caffemodel, deploy_prototxt):
    # no mean substraction

    # define caffe net
    net = caffe.Net(deploy_prototxt, caffemodel, caffe.TEST)
    transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
    transformer.set_transpose('data', (2, 0, 1))

    # get caffe prediction
    img = cv2.imread("example.jpg")
    img = cv2.resize(img, (227, 227), cv2.INTER_LINEAR) # the same way as resizing cv2.dnn.blobFromImage when crop=False
    net.blobs['data'].data[...] = transformer.preprocess('data', img)
    out = net.forward()
    print "caffe probs: " + str(out['prob'][0])

  # define openCv net
    cv_net = cv2.dnn.readNetFromCaffe(deploy_prototxt, caffemodel)

    # get opencv predictions:
    img_for_cv = cv2.imread("example.jpg")
    cv_blob = cv2.dnn.blobFromImage(img_for_cv, 1, (227,227), (), swapRB=False, crop=False)
    cv_net.setInput(cv_blob)
    prob = cv_net.forward()
    print "cv probs" + str(prob)


#  tested on different models:

#  normal reference caffemodel (but with some other mean):
caffe_vs_ocv_with_mean_subs("caffenet_1000.caffemodel", "caffenet_deploy_1000.prototxt")
#  my custom versions of caffenet and squeezenet with different number of output classes
caffe_vs_ocv_with_mean_subs("caffenet_5.caffemodel", "caffenet_deploy_5.prototxt")
caffe_vs_ocv_with_mean_subs("squeezenet_1.1.caffemodel", "squeezenet_deploy.prototxt")
#  all tests with mean substraction failed, giving completely wrong results

#  examples without mean substraction:
#  here differences between probabilities are tolerable, it works fine:
caffe_vs_ocv_simple("caffenet_model.caffemodel", "caffenet_deploy.prototxt")
caffe_vs_ocv_simple("caffenet_5.caffemodel", "caffenet_deploy_5.prototxt")
click to hide/show revision 2
None

updated 2018-07-16 12:43:32 -0600

berak gravatar image

dnn: classify with mean substraction, results different for caffe and opencv

This question is strongly connected to: http://answers.opencv.org/question/178680/how-to-use-meanbinaryproto-with-blobfromimages/

I'm working with OpenCV 3.4.1 and caffe 1.0.0

I have different results for classification in caffe and OpenCV only when I'm using mean subtraction, without it everything works fine. I have the same observation for some caffenet and squeezenet_v1.1 models. My code:

import cv2
import caffe
import numpy as np

#  function comparing results of image classification in opencv and caffe:
#  with mean substraction results don't match
def caffe_vs_ocv_with_mean_subs(caffemodel, deploy_prototxt):
    #  read mean
    blob = caffe.proto.caffe_pb2.BlobProto()
    with open("mean.binaryproto", 'rb') as f:
        blob.ParseFromString(f.read())
        data = np.array(blob.data).reshape([blob.channels, blob.height, blob.width])
        cv_mean = [np.mean(data[0]), np.mean(data[1]), np.mean(data[2])]

    # define caffe net
    net = caffe.Net(deploy_prototxt, caffemodel, caffe.TEST)
    transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
    transformer.set_mean('data', data)
    transformer.set_transpose('data', (2, 0, 1))

    # get caffe prediction
    img = cv2.imread("example.jpg")
    img = cv2.resize(img, (227, 227), cv2.INTER_LINEAR)
    net.blobs['data'].data[...] = transformer.preprocess('data', img)
    out = net.forward()
    print "mean: " + str(cv_mean)
    print "caffe probs: " + str(out['prob'][0])

    # define openCv net
    cv_net = cv2.dnn.readNetFromCaffe(deploy_prototxt, caffemodel)
    # get opencv predictions:
    img_for_cv = cv2.imread("example.jpg")
    #  swapRB=False, just like in http://answers.opencv.org/question/178680/how-to-use-meanbinaryproto-with-blobfromimages/,
    #  but I tried any combinations of swapRB, crop flags
    cv_blob = cv2.dnn.blobFromImage(img_for_cv, 1, (227,227), cv_mean, swapRB=False, crop=False)
    cv_net.setInput(cv_blob)
    prob = cv_net.forward()
    print "cv probs" + str(prob)


#  no mean substrucation - this works fine
def caffe_vs_ocv_simple(caffemodel, deploy_prototxt):
    # no mean substraction

    # define caffe net
    net = caffe.Net(deploy_prototxt, caffemodel, caffe.TEST)
    transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
    transformer.set_transpose('data', (2, 0, 1))

    # get caffe prediction
    img = cv2.imread("example.jpg")
    img = cv2.resize(img, (227, 227), cv2.INTER_LINEAR) # the same way as resizing cv2.dnn.blobFromImage when crop=False
    net.blobs['data'].data[...] = transformer.preprocess('data', img)
    out = net.forward()
    print "caffe probs: " + str(out['prob'][0])

  # define openCv net
    cv_net = cv2.dnn.readNetFromCaffe(deploy_prototxt, caffemodel)

    # get opencv predictions:
    img_for_cv = cv2.imread("example.jpg")
    cv_blob = cv2.dnn.blobFromImage(img_for_cv, 1, (227,227), (), swapRB=False, crop=False)
    cv_net.setInput(cv_blob)
    prob = cv_net.forward()
    print "cv probs" + str(prob)


#  tested on different models:

#  normal reference caffemodel (but with some other mean):
caffe_vs_ocv_with_mean_subs("caffenet_1000.caffemodel", "caffenet_deploy_1000.prototxt")
#  my custom versions of caffenet and squeezenet with different number of output classes
caffe_vs_ocv_with_mean_subs("caffenet_5.caffemodel", "caffenet_deploy_5.prototxt")
caffe_vs_ocv_with_mean_subs("squeezenet_1.1.caffemodel", "squeezenet_deploy.prototxt")
#  all tests with mean substraction failed, giving completely wrong results

#  examples without mean substraction:
#  here differences between probabilities are tolerable, it works fine:
caffe_vs_ocv_simple("caffenet_model.caffemodel", "caffenet_deploy.prototxt")
caffe_vs_ocv_simple("caffenet_5.caffemodel", "caffenet_deploy_5.prototxt")