2D 直方图
学习如何绘制 2D 直方图
1、 介绍
在前面的部分我们介绍了如何绘制一维直方图,之所以称为一维,是因为只考虑了图像的一个特征:灰度值,但是在 2D 直方图中我们就要考虑两个图像特征。对于彩色图像的直方图通常情况下我们需要考虑每个的颜色(Hue)和饱和度(Saturation)。根据这两个特征绘制 2D 直方图。OpenCV 的官方文档中包含一个创建彩色直方图的例子。本节就是要学习如何绘制颜色直方图,这会对我们下一节学习直方图投影有所帮助。
2、 OpenCV 中的 2D 直方图
使用函数 cv2.calcHist() 来计算直方图既简单又方便。如果要绘制颜色直方图的话,首先需要将图像的颜色空间从 BGR 转换到 HSV。(记住,计算二维直方图,要从 BGR 转换到 HSV)。计算 2D 直方图,函数的参数要做如下修改:
• channels=[0, 1] 因为我们需要同时处理 H 和 S 两个通道。
• bins=[180, 256]H 通道为 180, S 通道为 256。
• range=[0, 180, 0, 256]H 的取值范围在 0 到 180, S 的取值范围在 0 到 256。
代码如下:
import cv2
import numpy as np
img = cv2.imread('image/lufei.jpeg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hist = cv2.calcHist([hsv], [0,1], None, [180,256], [0,180,0,256])
3、Numpy 中 2D 直方图
Numpy 同样提供了绘制 2D 直方图的函数:np.histogram2d()。(还绘制 1D 直方图时我们使用的是 np.histogram())
import cv2
import numpy as np
img = cv2.imread('image/lufei.jpeg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hist,xbins,ybins = np.histogram2d(h.ravel(),s.ravel(),[180,256],[[0,180],[0,256]])
第一个参数是 H 通道,第二个参数是 S 通道,第三个参数是 bins 的数目,第四个参数是数值范围。
4 、绘制 2D 直方图
方法 1:使用 cv2.imshow() 我们得到结果是一个 180x256 的两维数组。所以我们可以使用函数 cv2.imshow() 来显示它。但是这是一个灰度图,除非我们知道不同颜色 H 通道的值,否则我们根本就不知道那到底代表什么颜色。
方法 2:使用 Matplotlib() 我们还可以使用函数matplotlib.pyplot.imshow()来绘制 2D 直方图,再搭配上不同的颜色图(color_map)。这样我们会对每个点所代表的数值大小有一个更直观的认识。但是跟前面的问题一样,你还是不知道那个数代表的颜色到底是什么。虽然如此,我还是更喜欢这个方法,它既简单又好用。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('image/lufei.jpeg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hist = cv2.calcHist([hsv], [0,1], None, [180,256], [0,180,0,256])
plt.imshow(hist,interpolation = 'nearest')
plt.show()
结果图:
方法 3: OpenCV 风格 在官方文档中有一个关于颜色直方图的例子。运行一下这个代码,你看到的颜色直方图也显示了对应的颜色。简单来说就是:输出结果是一副由颜色编码的直方图。效果非常好(虽然要添加很多代码)。
在那个代码中,作者首先创建了一个 HSV 格式的颜色地图,然后把它转
换成 BGR 格式。再将得到的直方图与颜色直方图相乘。作者还用了几步来去
除小的孤立的的点,从而得到了一个好的直方图。
import cv2
import numpy as np
from time import clock
import sys
#import cv2.video
if __name__ == '__main__':
hsv_map = np.zeros((180,256,3),np.uint8)
h,s = np.indices(hsv_map.shape[:2])
hsv_map[:,:,0] = h
hsv_map[:,:,1] = s
hsv_map[:,:,2] = 255
hsv_map = cv2.cvtColor(hsv_map, cv2.COLOR_HSV2BGR)
cv2.imshow('hsv_map', hsv_map)
cv2.namedWindow('hist',0)
hist_scale = 10
def set_scale(val):
global hist_scale
hist_scale = val
cv2.createTrackbar('scale', 'hist', hist_scale, 32, set_scale)
try:fn = sys.argv[1]
except:fn = 0
cam = video.create_capture(fn,fallback='synth:bg=image/22.png:class=chess:noise=0.05')
while(true):
flag,frame = cam.read()
cv2.imshow('camera', frame)
small = cv2.pyrDown(frame)
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
dark = hsv[:,:,2]<32
hsv[dark] = 0
h = cv2.calcHist([hsv], [0,1], None, [180,256], [0,180,0,256])
h = np.clip(h*0.005*hist_scale, 0, 1)
vis = hsv_map*h[:,:,np.newaxis] / 255.0
cv2.imshow('hist', vis)
ch = 0xFF & cv2.waitKey(1)
if ch == 27:
break
cv2.destroyAllWindows()
参考:OpenCV官方教程中文版(For Python)