opencv python 直方图

opencvfw 2019-06-28

Histograms - 1 : Find, Plot, Analyze !!!

理论

可以将直方图视为图形或绘图,它可以从中全面了解图像的强度分布. 它是在X轴上具有像素值(范围从0到255,并非总是)的图和在Y轴上的图像中的对应像素数.

查找直方图

BINS:像素值区间的像素数.例如将整个直方图分成16个子部分,每个子部分的值是其中所有像素数的总和,每个子部分称为“BIN”.

DIMS:收集数据的参数数量,在这种情况下,我们只收集有关一件事,强度值的数据,所以这里是1.

RANGE :要测量的强度值范围.通常,它是[0,256],即所有强度值.

1 OpenCV中的直方图计算

cv.calcHist(images,channels,mask,histSize,ranges [,hist [,accumulate]])

  1. images:它是uint8或float32类型的源图像。它应该用方括号表示,即“[img]”;
  2. channels:它也在方括号中给出.它是我们计算直方图的通道索引.例如,如果输入是灰度图像,则其值为[0].对于彩色图像,您可以通过[0],[1]或[2]分别计算蓝色,绿色或红色通道的直方图.
  3. mask:蒙版图像.要查找完整图像的直方图,它将显示为“无”.但是,如果要查找图像特定区域的直方图,则必须为其创建蒙版图像并将其作为蒙版.
  4. histSize:这代表我们的BIN计数.需要在方括号中给出.对于满量程,我们通过[256].
  5. ranges:这是我们的范围。通常,它是[0,256].

代码

import cv2
import numpy as np

img = cv2.imread('img.jpg')
hist = cv2.calcHist([img],[0],None,[256],[0,256])

hist是256x1数组,每个值对应于该图像中具有相应像素值的像素数

2 Numpy中的直方图计算

hist,bins = np.histogram(img.ravel(),256,[0,256])

hist与我们之前计算的相同. 但是bins将有257个元素,因为Numpy计算bins为0-0.99,1-1.99,2-2.99等.所以最终范围是255-255.99. 为了表示这一点,他们还在箱柜末尾添加256. 但我们不需要256.高达255就足够了.

Numpy还有另一个函数np.bincount(),它比(大约10倍)np.histogram()快得多。 因此,对于一维直方图,您可以更好地尝试. 不要忘记在np.bincount中设置minlength = 256.
例如,hist = np.bincount(img.ravel(),minlength = 256)

Note:OpenCV函数比np.histogram()快(大约40倍)

绘制直方图

1 使用Matplotlib

Matplotlib附带直方图绘图功能:matplotlib.pyplot.hist()

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('img.jpg',0)
plt.hist(img.ravel(),256,[0,256])
plt.show()

原图:
opencv python 直方图

直方图:
opencv python 直方图

或者可以使用matplotlib的正常图,这对BGR图有好处.需要首先找到直方图数据.
代码

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('img.jpg')

color = ('b','g','r')
for i,col in enumerate(color):
    histr = cv2.calcHist([img],[i],None,[256],[0,256])
    plt.plot(histr,color = col)
    plt.xlim([0,256])
plt.show()

opencv python 直方图

掩模的应用

我们使用cv.calcHist()来查找完整图像的直方图. 如果要查找图像某些区域的直方图, 只需在要查找直方图的区域上创建一个白色的蒙版图像,否则创建黑色. 然后将其作为掩模传递.

代码

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('img.jpg',0)

# create a mask
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_img = cv2.bitwise_and(img,img,mask = mask)

# Calculate histogram with mask and without mask
# Check third argument for mask
hist_full = cv2.calcHist([img],[0],None,[256],[0,256])
hist_mask = cv2.calcHist([img],[0],mask,[256],[0,256])

plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask,'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0,256])

plt.show()

opencv python 直方图

相关推荐