4.4 直方图的计算与显示

写在前面

1.直方图的概念:

      直方图其实就是一副图像的灰度级统计,设一副图像的灰度级为\[0,L-1\],则可以建立一个二维坐标系(x,y\),x取值\[0,L-1\],y取值为相应灰度级的像素数量。如果是归一化直方图,则y代表该灰度级在图像中的出现概率,且![](http://hi.csdn.net/attachment/201110/29/0_1319909647VzvY.gif)

2.函数原型

python调用Opencv直方图计算函数为:cv2.calcHist

cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]]) #返回hist

通过一例子了解函数中的参数:

#coding=utf-8
import cv2
import numpy as np
image = cv2.imread("D:/histTest.jpg", 0)
hist = cv2.calcHist([image],
    [0], #使用的通道
    None, #没有使用mask
    [256], #HistSize
    [0.0,255.0]) #直方图柱的范围
  • 第一个参数,表述我们要处理的img,一定要用方括号括起来(实际处理的是矩阵);

  • 第二个参数,用作计算直方图的通道,这里使用灰度图计算;

  • 第三个参数,Mask;处理没有使用,用None表示;

  • 第四个参数,用作表示我们将直方图分成几个直方柱表示
  • 第五个参数,表示直方图各个像素的值,[0.0, 255.0]表示直方图能表示像素值从0.0到255的像素。
  • 剩下两个参数,用的比较少。这里不做解释

3.计算和显示彩色图像不同通道的直方图

函数封装,便于使用:

def calcAndDrawHist(image, color):  
    hist= cv2.calcHist([image], [0], None, [256], [0.0,255.0])  
    minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(hist)  
    histImg = np.zeros([256,256,3], np.uint8)  
    hpt = int(0.9* 256);  

    for h in range(256):  
        intensity = int(hist[h]*hpt/maxVal)  
        cv2.line(histImg,(h,256), (h,256-intensity), color)  

    return histImg;

源代码:

import cv2    
import numpy as np    

def calcAndDrawHist(image, color):  
    hist= cv2.calcHist([image], [0], None, [256], [0.0,255.0])  
    minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(hist)  
    histImg = np.zeros([255,255,3], np.uint8)  
    hpt = int(0.9* 256);  

    for h in range(256):  
        intensity = int(hist[h]*hpt/maxVal)  
        cv2.line(histImg,(h,256), (h,256-intensity), color)

    return histImg
if __name__ == '__main__':  
    img = cv2.imread("G:/python project/lena.jpg")  
    b, g, r = cv2.split(img)  

    histImgB = calcAndDrawHist(b, [255, 0, 0])  
    histImgG = calcAndDrawHist(g, [0, 255, 0])  
    histImgR = calcAndDrawHist(r, [0, 0, 255])  

    cv2.imshow("histImgB", histImgB)  
    cv2.imshow("histImgG", histImgG) 
    cv2.imshow("histImgR", histImgR)  
    cv2.imshow("Img", img)  
    cv2.waitKey(0)  
    cv2.destroyAllWindows()

重点理解:

  • 函数返回的Hist参数以及后续处理;

  • 如何调用Opencv画图实现树状图绘制

运行结果:

挂,另外一种画折线图:

#coding=utf-8  
import cv2  
import numpy as np  

img = cv2.imread('G:/python project/lena.jpg')  
h = np.zeros((256,256,3)) #创建用于绘制直方图的全0图像  

bins = np.arange(256).reshape(256,1) #直方图中各bin的顶点位置  
color = [ (255,0,0),(0,255,0),(0,0,255) ] #BGR三种颜色  
for ch, col in enumerate(color):  
    originHist = cv2.calcHist([img],[ch],None,[256],[0,256])  
    cv2.normalize(originHist, originHist,0,255*0.9,cv2.NORM_MINMAX)  
    hist=np.int32(np.around(originHist))  
    pts = np.column_stack((bins,hist))  
    cv2.polylines(h,[pts],False,col)  

h=np.flipud(h)  

cv2.imshow('colorhist',h)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:

CSDN作者sunny原文:

这里的for循环是对三个通道遍历一次,每次绘制相应通道的直方图的折线。for循环的第一行是计算对应通道的直方图,经过上面的介绍,应该很容易就能明白。

这里所不同的是没有手动的计算直方图的最大值再乘以一个系数,而是直接调用了OpenCV的归一化函数。该函数将直方图的范围限定在0-255×0.9之间,与之前的一样。下面的hist= np.int32(np.around(originHist))先将生成的原始直方图中的每个元素四舍六入五凑偶取整(cv2.calcHist函数得到的是float32类型的数组),接着将整数部分转成np.int32类型。即61.123先转成61.0,再转成61。注意,这里必须使用np.int32(...)进行转换,numpy的转换函数可以对数组中的每个元素都进行转换,而Python的int(...)只能转换一个元素,如果使用int(...),将导致only length-1 arrays can be converted to Python scalars错误。

下面的pts = np.column_stack((bins,hist))是将直方图中每个bin的值转成相应的坐标。比如hist[0] =3,...,hist[126] = 178,...,hist[255] = 5;而bins的值为[[0],[1],[2]...,[255]]。使用np.column_stack将其组合成[0, 3]、[126, 178]、[255, 5]这样的坐标作为元素组成的数组。

最后使用cv2.polylines函数根据这些点绘制出折线,第三个False参数指出这个折线不需要闭合。第四个参数指定了折线的颜色。

当所有完成后,别忘了用h = np.flipud(h)反转绘制好的直方图,因为绘制时,[0,0]在图像的左上角。这在直方图可视化一节中有说明。

原创自:http://blog.csdn.net/sunny2038/article/details/9097989(作者:sunny2038)

results matching ""

    No results matching ""