Drawing Histogram in OpenCV-Python
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)
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, 2020Comments
-
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.
Then i modified the code a little bit.
ie changed the sixth line in code
b,g,r = cv2.split(img)
tob,g,r = img[:,:,0], img[:,:,1], img[:,:,2]
(because it works a little faster thancv2.split
).Now the output is something different. Below is the output.
I checked the values of
b,g,r
from both the codes. They are same.Difference lies in the output of
cv2.calcHist
. Result ofhist_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.
You can get my original image here: zzz.jpg
Thank you.
-
Abid Rahman K about 12 yearsWhat is the need for
copy
? And what is meant by calcHist() accept channel parameter? What does it actually denote? -
HYRY about 12 yearsyou 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 about 12 yearsyou mean c_contiguous? What is its significance?
-
Neon22 about 12 yearsnumpy 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 over 11 yearsbut is it me or the image size is not 300 * 256?
-
letmaik over 10 yearsIn 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 almost 6 years@user601836 I have the same problems