Python OpenCV 直方图 (五)

直方图

python 调用 calcHist 返回 hist (直方图)

calcHist 函数:

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

参数说明: images  --   图像对像

                     channels  --  用于计算直方图的通道

                     Mask  --  

                     histSize  --   表示直方图分成多少份(多少个直方柱)

                     ranges  --  表示直方图中各个像素的值,[0.0, 256.0]表示直方图能表示像素值从0.0到256的像素

                     hist   --   

                     accumulate  --  是一个布尔值,表示直方图是否叠加


灰度图计算

#!/usr/bin/env python  
# encoding: 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]) #直方图柱的范围  


彩色图像(多通道)直方图

使用 OpenCV 方法

步骤: 1. 读取并分离各通道

             2.计算每个通道的直方图

#!/usr/bin/env python  
# encoding: utf-8  

import cv2  
import numpy as np  
   
  
def calcAndDrawHist(image, color):    
    hist= cv2.calcHist([image], [0], None, [256], [0.0,255.0]) 
    '''
    minMaxLoc寻找矩阵(一维数组当作向量,用Mat定义) 中最小值和最大值的位置     
    注意:多通道图像在使用minMaxLoc()函数是不能给出其最大最小值坐标的,因为每个像
    素点其实有多个坐标,所以是不会给出的。因此在编程时,这2个位置应该给NULL。
    '''
    minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(hist) 

    #创建绘制直方图的的图像,由于值全为0 所以它是黑色的 
    histImg = np.zeros([256,256,3], np.uint8)  
      
    hpt = int(0.9* 256) #直方图的范围限定在0-255×0.9之间   
        
    for h in range(256):    
        intensity = int(hist[h]*hpt/maxVal)  # 计算直方图的最大值再乘以一个系数
        
        '''
        绘制线
        histImg --   图像
        (h,256)  --  线段的第一个端点
        (h,256-intensity)  --  线段的第二个端点
        color  --  线段的颜色
        '''  
        cv2.line(histImg,(h,256), (h,256-intensity), color)   
            
    return histImg; 

if __name__ == '__main__':    
    img = cv2.imread("mini.jpg")    
    b, g, r = cv2.split(img)     # 使用Opencv 自带的分离函数 split   
    
    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() 

在一张图上绘制,这样不用再分离通道,用折线来描绘直方图的边界即可

#!/usr/bin/env python  
# encoding: utf-8  

import cv2  
import numpy as np  


img = cv2.imread('mini.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]) 

    '''
    OpenCV的归一化函数。该函数将直方图的范围限定在0-255×0.9之间
    '''   
    cv2.normalize(originHist, originHist,0,255*0.9,cv2.NORM_MINMAX)  

    '''
    先将生成的原始直方图中的每个元素四舍六入五凑偶取整
   (cv2.calcHist函数得到的是float32类型的数组) 
    注意,这里必须使用np.int32(...)进行转换,
    numpy的转换函数可以对数组中的每个元素都进行转换,
    而Python的int(...)只能转换一个元素,如果使用int(...),
    将导致only length-1 arrays can be converted to Python scalars错误。 
    '''
    hist=np.int32(np.around(originHist))  

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

    '''
    polylines 根据这些点绘制出折线
    False  --  指出这个折线不需要闭合
    col   --  指定了折线的颜色
    '''
    cv2.polylines(h,[pts],False,col)    

'''
反转绘制好的直方图,因为绘制时,[0,0]在图像的左上角
'''         
h=np.flipud(h)    
         
cv2.imshow('colorhist',h)    
cv2.waitKey(0)   


使用Numpy 直方图计算

NumPy中histogram函数应用到一个数组返回一对变量:直方图数组和箱式向量。注意:matplotlib也有一个用来建立直方图的函数(叫作hist,正如matlab中一样)与NumPy中的不同。主要的差别是pylab.hist自动绘制直方图,而numpy.histogram仅仅产生数据。

#!/usr/bin/env python  
# encoding: utf-8  

import cv2  
import numpy as np  
  
img = cv2.imread('mini.jpg')  
h = np.zeros((300,256,3))  
bins = np.arange(257)  
bin = bins[0:-1]  
color = [ (255,0,0),(0,255,0),(0,0,255) ]  
  
for ch,col in enumerate(color):  
    item = img[:,:,ch]  
    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)  
  
h=np.flipud(h)  
  
cv2.imshow('img',h)  
cv2.waitKey(0)  























































你可能感兴趣的:(Python,OpenCV)