那么,图像直方图到底是什么?
图片
图像的构成是由像素点构成的,每个像素点的值代表着该点的颜色(灰度图或者彩色图)。所谓直方图就是对图像的中的这些像素点的值进行统计,得到一个统一的整体的灰度概念。直方图表示图像中颜色的分布。可以将其可视化为图表(或曲线图),以直观地了解强度(像素值)分布。直方图的好处就在于可以清晰了解图像的整体灰度分布,这对于计算机视觉处理图片有关重要。
一般情况下直方图都是灰度图像,直方图x轴是灰度值(一般0~255),y轴就是图像中每一个灰度级对应的像素点的个数。
灰度空间图片直方图
图片直方图的获取,opencv已经帮我们集成了函数,当然numpy也同样可以 获取
from matplotlib import pyplot as plt
import numpy as np
import cv2
image = cv2.imread("1.jpg")
img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
hist = cv2.calcHist([img], [0], None, [256], [0, 256])
#numpy方法读取-np.histogram()
#hist_np,bins = np.histogram(img.ravel(),256,[0,256])
#numpy的另一种方法读取-np.bincount()
#hist_np1 = np.bincount(img.ravel(),minlength=256)
cv2.imshow("gray", img)
plt.figure()
plt.title("Grayscale Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
plt.plot(hist)
plt.show()
代码截图
cv2.calcHist(),该函数传递5个参数:
以上展示了图片在灰度值中的颜色直方图,当然,我们的图片是R G B的三色图片,我们也可以分别展示图片在R G B 空间内的图片直方图。
彩色空间图片直方图
from matplotlib import pyplot as plt
import numpy as np
import cv2
image = cv2.imread("1.jpg")
cv2.imshow("image", image)
chans = cv2.split(image)
colors = ("b", "g", "r")
plt.figure()
plt.title("'Flattened' Color Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
features = []
for (chan, color) in zip(chans, colors):
hist = cv2.calcHist([chan], [0], None, [256], [0, 256])
features.extend(hist)
plt.plot(hist, color = color)
plt.xlim([0, 256])
plt.show()
代码截图
chans = cv2.split(image)函数把图片分别分割成 R G B 三色空间
分别把三色空间的 R G B 空间传入cv2.calcHist([chan], [0], None, [256], [0, 256])函数来生成不同空间内的颜色图片直方图,最后把图片显示出来
cv2.calcHist函数可以接受mask 来进行图片直方图的显示,默认计算图片的所有区域,但是有时候我们不需要图片的所有区域,我们可以使用mask来扣自己需要的图片区域,进而可以进行自己想要图片区域的直方图
mask 图片直方图
from matplotlib import pyplot as plt
import numpy as np
import cv2
image = cv2.imread("1.jpg")
img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
mask = np.zeros(img.shape[:2],np.uint8)
mask[100:500,100:500] = 255
mask_img = cv2.bitwise_and(img,img,mask=mask)
hist = cv2.calcHist([img], [0], mask, [256], [0, 256])
cv2.imshow("mask", mask_img)
plt.figure()
plt.title("Grayscale Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
plt.plot(hist)
plt.show()
代码截图
首先我们获取图片的尺寸img.shape[:2],有了图片的尺寸
我们可以标注自己需要的图片区域mask[100:500,100:500] = 255
使用cv2.bitwise_and 函数把原来图片中的需要的局部区域提取出来,我们可以show一下,看看是否是自己需要的区域
有了mask的区域,使用cv2.calcHist([img], [0], mask, [256], [0, 256])函数,传递mask 参数,进而可以实现mask图片的直方图显示。
这种方法通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。
这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来X光图像中更好的骨骼结构显示以及曝光过度或者曝光不足照片中更好的细节。这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景噪声的对比度并且降低有用信号的对比度。
图片直方图均衡化
有两个问题比较难懂,一是为什么要选用累积分布函数,二是为什么使用累积分布函数处理后像素值会均匀分布。
直方图均衡化包括三个步骤:
from matplotlib import pyplot as plt
import numpy as np
import cv2
image = cv2.imread("1.jpg")
img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
res = cv2.equalizeHist(img)
cv2.imshow('img',img)
cv2.imshow('res',res)
cv2.waitKey(0)
代码截图
opencv 使用此函数res = cv2.equalizeHist(img),对图片进行均衡化进行处理,此函数是opencv全局化操作,这个操作在我们需要局部调整时不太适用,同理mask参数,opencv存在一种局部化处理的函数cv2.createCLAHE(),此函数接受一个局部尺寸参数数据
局部化处理
from matplotlib import pyplot as plt
import numpy as np
import cv2
image = cv2.imread("1.jpg")
img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#res = cv2.equalizeHist(img)
cla = cv2.createCLAHE(clipLimit=2,tileGridSize=(10,10))
res = cla.Apply(img)
cv2.imshow('img',img)
cv2.imshow('res',res)
cv2.waitKey(0)
代码截图
图片直方图在相识图片搜索引擎中起到了至关重要的作用,如何使用图片直方图来进行相识图片的搜索,我们下期分享,帮你打造一款属于自己的相识图片搜索引擎。