长春网络建站/seo外链资源
学习之前准备工作:
如何寻找opencv-python官网教程:
① 浏览器收索 opencv,打开opencv的官网;
② TutorialsOpenCV modulesOpencv-Python Tutorials;
1. 原理
直方图:针对的是灰度图,或是 RGB 彩色图像的单通道图像(其实也是灰度图像),默认情况下,横坐标:图像的灰度级;纵坐标:对应的灰度级的个数,通过图像,你能了解图像灰度的整体分布情况。
2. 怎么画
① 概念:
OpenCV 是什么:
OpenCV(Open Source Computer Vision Library),开源计算机视觉库,用 C++ 语言编写,由一系列 C 函数和少量 C++ 类构成,同时提供了 Python、C++、MATLAB等常用编程语言接口,该库具有2500多种优化算法,其中包括一整套经典和最新的计算机视觉和机器学习算法。
Python 之 cv2 库(OpenCV - python)的应用,先放一张 官方图,如图1所示
其实:图1 的直方图 是 根据原图的灰度图所画的。
自己动手画:
② 统计直方图:
方法1:利用 OpenCV
Hist = cv2.calcHist([img], [0], None, [256], [0, 256])
方法2:利用 numpy
- hist, bins = np.histogram(img.ravel(), 256, [0, 256]) #bins:灰度级区间数
- hist = np.bincount(img.ravel(), minlength = 256) #minlength: minimum number of bins for the output array.
注:np.bincount 速度比 np.hisgoram 快10倍,而 OpenCV 比 np.hisgoram 快40倍,所以还是使用OpenCV。
方法3:利用matplotlib中的pyplot,plt.hist()可以统计并绘制直方图
plt.hist(img.ravel(), 256, [0, 256])
③ 绘制直方图:
方法1:利用 matplotlib
利用:plt.plot() 即可,如图2所示,代码如下所示:
方法2:利用 opencv
官网:Well, here you adjust the values of histograms along with its bin values to look like x,y coordinates so that you can draw it usingcv2.line()or cv2.polyline() function to generate same image as above. This is already available with OpenCV-Python2 official samples.Check the Code
在 github 没有找到代码,感兴趣的话可以自己写.
用opencv绘制直方图相对复杂,一般我们直接使用:plt.plot().
④ 显示直方图:
plt.show()
import cv2
import numpy as np
from matplotlib import pyplot as pltimg = cv2.imread("src.jpg",0)## 采用np.histogram()
hist, bins = np.histogram(img.ravel(), 256, [0, 256]) #bins = 257
plt.plot(hist, "g")## 采用np.bincount()
hist, bins = cv2.bincount(img.ravel(), minlength = 256)
plt.plot(hist, "b")## 采用cv2.calcHist()
hist = cv2.calcHist([img], [0], None, 256, [0, 256])
plt.plot(hist, "r")##采用plt.hist()
plt.hist(img.ravel(), 256, [0, 256])plt.show()
注:hist,bins = np.histogram()函数的返回值 bins = 257,因为 Numpy 计算 bins 的方式为:0-0.99,1-1.99,2-2.99 等. 所以最后一个范围是 255-255.99. 为了表示它,所以在 bins 的结尾加上了 256。但是我们不需要 256,到 255 就够了。
由图2可知,直方图采用 numpy 和 opencv 统计所达到的可视化效果图相同,采用 matplotlib 统计直方图,可视化效果有些不同。
3. 解释直方图
原图灰度图比较暗的点 表示 直方图灰度值比较小的点,反之亦然,我们可以通过直方图能够大致判断图像的色调,是属于低调,或是高调,亦或中间调的图像。
① 图1 : 大部分像素在处于低调和高调,少量处于中间调,低调像素整体要多于高调,因此我们可以判断这张图像对比度 较强;
② 图2 : 大部分像素处于低调和中间调,高调相对较少(太阳与天空的).
附加:
Q1:有的人可能问了,对于一幅图像,我能不能将图像的B、G、R 每个通道的灰度直方图画在一个图上呢,这样方便观察.
A1:当然可以,不过在此先得介绍,Python自带的一个内置函数:enumerate()
enumerate()的作用:
# 对一个列表或数组既要遍历索引又要遍历元素时,使用内置 enumerrate 函数会有更加直接,优美的做法,enumerate 会将数组或列表组成一个索引序列,使我们再获取索引和索引内容的时候更加方便.
程序如下:
import cv2
import numpy as np
from matplotlib import pyplot as pltimg = cv2.imread("1.jpg")
color = ("b", "g", "r") #小写for i, col in enumerate(color):hist = cv2.calcHist([img], [i], None, [256], [0, 256])plt.plot(hist, col)plt.xlim([0, 256])plt.show()
Q2:有的人,可能又得问了,我只想对图像的一部分进行统计直方图,可以吗?
A2:可以,使用掩膜即可.
程序如下:
import cv2
import numpy as np
from matplotlib import pyplot as pltimg = cv2.imread(r"C:Userspwg123Desktoptimg.jpg", 0)mask = np.zeros(img.shape[:2], np.uint8)
mask[50:150, 100:250] = 255masked_img = cv2.bitwise_and(img, img, mask = 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.axis("off"), plt.title("Original Image", y= -0.1) # y = -0.1 设置标题在下方
plt.subplot(222), plt.imshow(mask, "gray"), plt.axis("off"), plt.title("Mask", y = -0.1)
plt.subplot(223), plt.imshow(masked_img, "gray"), plt.axis("off"), plt.title("Masked Img", y = -0.1)
plt.subplot(224), plt.plot(hist_full, color = "g"), plt.plot(hist_mask, color = "r"), plt.xlabel("Histogram")# plt.xlim([0, 256])plt.show()