Ask Your Question

python opencv compare histograms

asked 2012-08-20 06:56:34 -0500

mrgloom gravatar image

updated 2012-08-20 08:11:13 -0500

I'm trying to compare 2 histograms in python.

But it give me an error "sc= cv.CompareHist(hist_item1, hist_item2, cv.CV_COMP_CORREL) TypeError: Expected CvHistogram for argument 'hist1'"

here is the code:

import cv2
import cv
import numpy as np
import time

img1 = cv2.imread('C:/ICP/buterfly_1.jpg')
img1= cv2.cvtColor(img1,cv.CV_BGR2HSV)
img2 = cv2.imread('C:/ICP/buterfly_0.jpg')
img2= cv2.cvtColor(img2,cv.CV_BGR2HSV)
h = np.zeros((300,256,3))

bins = np.arange(256).reshape(256,1)
color = [ (255,0,0),(0,255,0),(0,0,255) ]

for ch, col in enumerate(color):
    hist_item1 = cv2.calcHist([img1],[ch],None,[256],[0,255])
    hist_item2 = cv2.calcHist([img2],[ch],None,[256],[0,255])
    sc= cv.CompareHist(hist_item1, hist_item2, cv.CV_COMP_CORREL)
    pts = np.column_stack((bins,hist))


UPDATE:i found this code and it seems work, but I think it's not opencv-style, maybe better way exist?

import numpy
from PIL import Image
import cv2

def similarness(image1,image2):
Return the correlation distance be1tween the histograms. This is 'normalized' so that
1 is a perfect match while -1 is a complete mismatch and 0 is no match.
    # Open and resize images to 200x200
    i1 =,200))
    i2 =,200))

    # Get histogram and seperate into RGB channels
    i1hist = numpy.array(i1.histogram()).astype('float32')
    i1r, i1b, i1g = i1hist[0:256], i1hist[256:256*2], i1hist[256*2:]
    # Re bin the histogram from 256 bins to 48 for each channel
    i1rh = numpy.array([sum(i1r[i*16:16*(i+1)]) for i in range(16)]).astype('float32')
    i1bh = numpy.array([sum(i1b[i*16:16*(i+1)]) for i in range(16)]).astype('float32')
    i1gh = numpy.array([sum(i1g[i*16:16*(i+1)]) for i in range(16)]).astype('float32')
    # Combine all the channels back into one array
    i1histbin = numpy.ravel([i1rh, i1bh, i1gh]).astype('float32')

    # Same steps for the second image
    i2hist = numpy.array(i2.histogram()).astype('float32')
    i2r, i2b, i2g = i2hist[0:256], i2hist[256:256*2], i2hist[256*2:]
    i2rh = numpy.array([sum(i2r[i*16:16*(i+1)]) for i in range(16)]).astype('float32')
    i2bh = numpy.array([sum(i2b[i*16:16*(i+1)]) for i in range(16)]).astype('float32')
    i2gh = numpy.array([sum(i2g[i*16:16*(i+1)]) for i in range(16)]).astype('float32')
    i2histbin = numpy.ravel([i2rh, i2bh, i2gh]).astype('float32')

    return cv2.compareHist(i1histbin, i2histbin, 0)

and I find another method with old cv namespace

import cv
def compute_histogram(src, h_bins = 30, s_bins = 32, scale = 10):
    #create images
    hsv = cv.CreateImage(cv.GetSize(src), 8, 3)
    hplane = cv.CreateImage(cv.GetSize(src), 8, 1)
    splane = cv.CreateImage(cv.GetSize(src), 8, 1)
    vplane = cv.CreateImage(cv.GetSize(src), 8, 1)

    planes = [hplane, splane ...
edit retag flag offensive close merge delete


In your last question you touch a very different topic so I think it is better to post it as a new separate question.

Ilya Lysenkov gravatar imageIlya Lysenkov ( 2012-08-20 12:32:29 -0500 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2012-08-20 12:30:41 -0500

In your original code you use cv.CompareHist but cv namespace is deprecated. Try to use cv2.compareHist.

edit flag offensive delete link more


Ok, now all 3 ways is working, but what is the best/fast and more opencv-way method? And why if we use HSV space we don't use v-plane?

mrgloom gravatar imagemrgloom ( 2012-08-21 01:05:36 -0500 )edit

#1 is the best choice. It is the opencv-way method, the code is much cleaner than other solutions.

v-plane corresponds to lightness so it is not used to get invariance to changes in lighting.

Ilya Lysenkov gravatar imageIlya Lysenkov ( 2012-08-21 13:14:15 -0500 )edit
Login/Signup to Answer

Question Tools


Asked: 2012-08-20 06:56:34 -0500

Seen: 7,254 times

Last updated: Aug 20 '12