Drawing Histogram in OpenCV-Python

20,361

You should copy the array:

b,g,r = img[:,:,0].copy(), img[:,:,1].copy(), img[:,:,2].copy()

But, since calcHist() can accept channels parameter, you need not to split your img to three array.

import cv2
import numpy as np

img = cv2.imread('zzzyj.jpg')
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_item = cv2.calcHist([img],[ch],None,[256],[0,255])
    cv2.normalize(hist_item,hist_item,0,255,cv2.NORM_MINMAX)
    hist=np.int32(np.around(hist_item))
    pts = np.column_stack((bins,hist))
    cv2.polylines(h,[pts],False,col)

h=np.flipud(h)

cv2.imshow('colorhist',h)
cv2.waitKey(0)
Share:
20,361
Abid Rahman K
Author by

Abid Rahman K

"I prefer my application crashing than getting wrong answers." Contact me at [email protected] Visit my blog : http://opencvpython.blogspot.com/ Visit : Remove Convexity Defects of a Sudoku Square Visit : http://stackoverflow.com/questions/9413216/simple-digit-recognition-ocr-in-opencv-python Visit : Simple watershed sample in OpenCV-Python

Updated on August 03, 2020

Comments

  • Abid Rahman K
    Abid Rahman K almost 4 years

    I was just trying to draw histogram using new OpenCV Python interface ( cv2 ).

    Below is the code i tried:

    import cv2
    import numpy as np
    import time
    
    img = cv2.imread('zzz.jpg')
    h = np.zeros((300,256,3))
    b,g,r = cv2.split(img)
    bins = np.arange(256).reshape(256,1)
    color = [ (255,0,0),(0,255,0),(0,0,255) ]
    
    for item,col in zip([b,g,r],color):
        hist_item = cv2.calcHist([item],[0],None,[256],[0,255])
        cv2.normalize(hist_item,hist_item,0,255,cv2.NORM_MINMAX)
        hist=np.int32(np.around(hist_item))
        pts = np.column_stack((bins,hist))
        cv2.polylines(h,[pts],False,col)
    
    h=np.flipud(h)
    
    cv2.imshow('colorhist',h)
    cv2.waitKey(0)
    

    And it works fine. Below is the resulting histogram i obtained.

    enter image description here


    Then i modified the code a little bit.

    ie changed the sixth line in code b,g,r = cv2.split(img) to b,g,r = img[:,:,0], img[:,:,1], img[:,:,2] (because it works a little faster than cv2.split).

    Now the output is something different. Below is the output.

    enter image description here


    I checked the values of b,g,r from both the codes. They are same.

    Difference lies in the output of cv2.calcHist. Result of hist_item is different in both the cases.

    Question:

    How does it happen? Why the result of cv2.calcHist is different when inputs are same?

    EDIT

    I tried a different code. Now, a numpy version of my first code.

    import cv2
    import numpy as np
    
    img = cv2.imread('zzz.jpg')
    h = np.zeros((300,256,3))
    b,g,r = img[:,:,0],img[:,:,1],img[:,:,2]
    bins = np.arange(257)
    bin = bins[0:-1]
    color = [ (255,0,0),(0,255,0),(0,0,255) ]
    
    for item,col in zip([b,g,r],color):
        N,bins = np.histogram(item,bins)
        v=N.max()
        N = np.int32(np.around((N*255)/v))
        N=N.reshape(256,1)
        pts = np.column_stack((bin,N))
        cv2.polylines(h,[pts],False,col,2)
    
    h=np.flipud(h)
    
    cv2.imshow('img',h)
    cv2.waitKey(0)
    

    And the output is same as first one.

    enter image description here

    You can get my original image here: zzz.jpg

    Thank you.

  • Abid Rahman K
    Abid Rahman K about 12 years
    What is the need for copy? And what is meant by calcHist() accept channel parameter? What does it actually denote?
  • HYRY
    HYRY about 12 years
    you can call cv2.calcHist([img],[CH],None,[256],[0,255]) to calculate the histogram of channel CH of img, that is img[:, :, CH]. You need to copy the array because data in img[:, :, 0] is not continuous.
  • Abid Rahman K
    Abid Rahman K about 12 years
    you mean c_contiguous? What is its significance?
  • Neon22
    Neon22 about 12 years
    numpy is more efficent at manipulating arrays and is used in cv2. the python split operator doesn't keep all the data together. the copy operator collects them neatly.
  • user601836
    user601836 over 11 years
    but is it me or the image size is not 300 * 256?
  • letmaik
    letmaik over 10 years
    In the end, it's really the task of OpenCV's Python wrapper to make sure that the array is C-contiguous, by calling np.ascontiguousarray. Just my 2 cents..
  • dorbodwolf
    dorbodwolf almost 6 years
    @user601836 I have the same problems