Ask Your Question
0

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

asked 2018-07-16 10:29:24 -0600

szymonk gravatar image

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

berak gravatar image

This question is strongly connected to: http://answers.opencv.org/question/17...

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")
edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
2

answered 2018-07-24 10:31:29 -0600

szymonk gravatar image

I changed line:

transformer.set_mean('data', data)

to:

transformer.set_mean('data', np.array([np.mean(data[0]), np.mean(data[1]), np.mean(data[2])]))

and it's fine. caffe.io.transformer does pixelwise mean subtraction instead of channelwise subtraction and this caused a problem. When I apply operation np.max(np.abs(a - b)) to compare blobs I still get a small error in order of magnitude 1e-5. But for me it doesn't make much difference, so I didin't investigate it further to long, I think it should be plain 0 though.

edit flag offensive delete link more
0

answered 2018-07-16 11:39:01 -0600

dkurt gravatar image

@szymonk, please compare compare both inputs: cv_blob and net.blobs['data'].data[...]. Does them similar or not? You may use np.max(np.abs(a - b)) for it.

edit flag offensive delete link more

Comments

no, they are not similar in version with mean subtraction. They are only similar in version without mean subtraction.

szymonk gravatar imageszymonk ( 2018-07-16 12:00:40 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-07-16 10:29:24 -0600

Seen: 1,300 times

Last updated: Jul 24 '18