目录:
- 1.绘制直方图
- 1)一维直方图
- 2)2D直方图
- 2.直方图均衡化
- 1)全局直方图均衡化
- 2)CLAHE(限制对比度的自适应直方图均衡化)-->局部
- 3.直方图反向投影
一、绘制直方图
直方图:统计每个像素在图像矩阵中出现的次数或概率。
OpenCV函数:
绘制直方图
cv2.calcHist(images, channels, mask, histSize, ranges, hist=None, accumulate=None)
参数:
img:输入图像,为列表,如[img]。
channels: 计算的通道,为列表,如[0]表示单通道,[0, 1]统计两个通道。
mask: 掩模,和输入图像大小一样的矩阵,为1的地方会进行统计(与图像逻辑与后再统计);无掩模时为None。
histSize: 每一个channel对应的bins(柱子)个数,为列表,如[256]表示256个像素值。
ranges: bins的边界,为列表,如[0,256]表示像素值范围在0-256之间。-->使用切片的原理,含前不含后。
1)一维直方图
一般将图像从BGR转换为灰度图来绘制一维直方图,也可绘制单通道的1D直方图。
# 1)一维直方图
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("image/1.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图
# 绘制灰度图的直方图
hist_gray = cv2.calcHist(images=[gray], channels=[0], mask=None, histSize=[256], ranges=[0, 256])
# 绘制单通道B的直方图
hist_B = cv2.calcHist([img], [0], None, [256], [0, 256])
# 绘制单通道G的直方图
hist_G = cv2.calcHist([img], [1], None, [256], [0, 256])
# 绘制单通道R的直方图
hist_R = cv2.calcHist([img], [2], None, [256], [0, 256])
plt.plot(hist_gray, color="gray", label="Gray")
plt.plot(hist_B, color="b", label="B")
plt.plot(hist_G, color="g", label="G")
plt.plot(hist_R, color="r", label="R")
plt.show()
一维直方图.png
2)2D直方图
对于彩色图片,需将图像从BGR转换为HSV,我们通过Hue (色度,范围[0, 179] )和Saturation(饱和度,范围[0, 255])两个特征来绘制2D直方图。
# 2)2D直方图
import cv2
img = cv2.imread("image/1.jpg")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 转化为HSV图
# 绘制2D直方图
hist_hsv = cv2.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])
cv2.namedWindow("hist_hsv", cv2.WINDOW_NORMAL)
cv2.imshow("hist_hsv", hist_hsv)
cv2.waitKey(0)
cv2.destroyWindow()
二维直方图.png
二、直方图均衡化
直方图均衡化是利用直方图,调整图像对比度的一种方法。
主要用于图像增强,如:图像去雾。
1)全局直方图均衡化
OpenCV函数:
1)全局直方图均衡化
dst = cv2.equalizeHist(src)
参数:
src: 图像对象矩阵,必须为单通道的uint8类型的矩阵数据
dst: 输出图像矩阵(和src的shape一样)
示例:
# 1)全局直方图均衡化
import cv2
import matplotlib.pyplot as plt
src = cv2.imread("image/7.jpg", cv2.IMREAD_GRAYSCALE)
# 全局直方图均衡化
dst = cv2.equalizeHist(src)
# 原直方图
hist_src = cv2.calcHist([src], [0], None, [256], [0, 256])
# 全局均衡化后的直方图
hist_dst = cv2.calcHist([dst], [0], None, [256], [0, 256])
# 结合matplotlib展示多张图片
plt.subplot(221), plt.imshow(src, cmap="gray"), plt.title("Src Image")
plt.xticks([]), plt.yticks([])
plt.subplot(222), plt.imshow(dst, cmap="gray"), plt.title("Dst Image")
plt.xticks([]), plt.yticks([])
plt.subplot(223), plt.plot(hist_src, color="r", label="hist_src"), plt.legend()
plt.subplot(224), plt.plot(hist_dst, color="b", label="hist_dst"), plt.legend()
plt.show()
全局直方图均衡化.png
2)CLAHE(限制对比度的自适应直方图均衡化)
限制对比度的自适应直方图均衡(CLAHE,Contrast Limited Adaptive Histogram Equalization),图像被分成称为“tile”的小块(在OpenCV中,tileSize默认为8x8),然后对每一个小块进行直方图均衡化。
但若小块内有噪声,影响很大,需要通过限制对比度来进行抑制,即限制对比度自适应直方图均衡化。如果限制对比度的阈值设置为40,在局部直方图分布中某个像素值出现次数为45,那么多出的5次像素点会被去掉,平均成其他像素值。
OpenCV函数:
2)CLAHE(限制对比度自适应均衡化)
clahe = cv2.createCLAHE(clipLimit=None, tileGridSize=None)
dst = clahe.apply(src)
参数:
clipLimit: 限制对比度的阈值,默认为40,直方图中像素值出现次数大于该阈值,多余的次数会被重新分配。
tileGridSize: tile块的大小,如tileGridSize=(8,8),默认为(8,8)。
示例:
# 2)CLAHE(限制对比度的自适应直方图均衡化)
import cv2
import matplotlib.pyplot as plt
src = cv2.imread("image/8.jpg", cv2.IMREAD_GRAYSCALE)
# 1.全局直方图均衡化
img_equalize = cv2.equalizeHist(src)
# 2.CLAHE自适应均衡化
# createCLAHE(clipLimit=None, tileGridSize=None)
clahe = cv2.createCLAHE(clipLimit=40, tileGridSize=(8, 8))
img_clahe = clahe.apply(src)
# 原直方图
hist_src = cv2.calcHist([src], [0], None, [256], [0, 256])
# 全局均衡化后的直方图
hist_equalize = cv2.calcHist([img_equalize], [0], None, [256], [0, 256])
# CLAHE均衡化后的直方图
hist_clahe = cv2.calcHist([img_clahe], [0], None, [256], [0, 256])
# 结合matplotlib展示多张图片
plt.subplot(231), plt.imshow(src, cmap="gray"), plt.title("Src Image")
plt.xticks([]), plt.yticks([])
plt.subplot(232), plt.imshow(img_equalize, cmap="gray"), plt.title("Image after Equalzie")
plt.xticks([]), plt.yticks([])
plt.subplot(233), plt.imshow(img_clahe, cmap="gray"), plt.title("Image after CLAHE")
plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.plot(hist_src, color="b", label="hist_src"), plt.legend()
plt.subplot(235), plt.plot(hist_equalize, color="g", label="hist_equalize"), plt.legend()
plt.subplot(236), plt.plot(hist_clahe, color="r", label="hist_clahe"), plt.legend()
plt.show()
CLAHE自适应均衡化.png
三、直方图反向投影
直方图反向投影主要用于图像分割或查找图像中感兴趣的对象。
直方图反向投影返回的图像,与输入图像具有相同的大小(但是单个通道),其中每个新的像素值对应于该像素属于ROI(感兴趣区域)的概率。越相似,概率值越大,颜色越靠近白色。
OpenCV直方图反向投影流程:
1)获取感兴趣对象的直方图
calcHist(images, channels, mask, histSize, ranges, hist=None, accumulate=None)
2)调用calcBackProject()之前,需要对直方图进行归一化。
normalize(src, dst, alpha=None, beta=None, norm_type=None, dtype=None, mask=None)
参数:
src: 输入图片
dst: 输出图片
alpha: 阈值下限
beta: 阈值上限
norm_type: 归一化的类型。包括:
NORM_INF = 1
NORM_L1 = 2
NORM_L2 = 4
NORM_L2SQR = 5
NORM_MINMAX = 32
dtype: 为负数时,dst的大小和图像深度类型均与src一致。为正数时,由dtype属性指定dst的图像深度类型。
mask: 掩膜
3)反向投影
calcBackProject(images, channels, hist, ranges, scale, dst=None)
参数:
images: 输入图像列表,如[img]。
channels: 用于计算反向投影的通道列表,与hist直方图维度相匹配。
hist: 感兴趣区域的直方图。
ranges: 直方图中每个维度bin的取值范围。
scale: 反向投影的图像像素的伸缩因子。
4)圆盘卷积
kernel = cv2.getStructuringElement(shape=cv2.MORPH_ELLIPSE, ksize=(5, 5))
dst = cv2.filter2D(dst, -1, kernel)
5)图像二值化
ret, thresh = threshold(src, thresh, maxval, type, dst=None)
6)抠出目标图像中的感兴趣部分
thresh = cv2.merge((thresh, thresh, thresh))
res = cv2.bitwise_and(target, thresh)
示例:
import cv2
# 感兴趣对象ROI
roi = cv2.imread("image/10.jpg")
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) # 转化为HSV图
# 目标图像
target = cv2.imread("image/9.jpg")
hsv_target = cv2.cvtColor(target, cv2.COLOR_BGR2HSV) # 转化为HSV图
# 1)统计ROI的直方图
hist_roi = cv2.calcHist([hsv_roi], [0, 1], None, [180, 256], [0, 180, 0, 256])
# 2)直方图归一化: 在调用calcBackProject之前,需要对hist_roi进行归一化
cv2.normalize(hist_roi, hist_roi, 0, 255, cv2.NORM_MINMAX)
# 3)反向投影: calcBackProject
backProject = cv2.calcBackProject([hsv_target], [0, 1], hist_roi, [0, 180, 0, 256], 1)
# 4)圆盘卷积
kernel = cv2.getStructuringElement(shape=cv2.MORPH_ELLIPSE, ksize=(5, 5))
backProject = cv2.filter2D(backProject, -1, kernel)
# 5)图像二值化
ret, thresh = cv2.threshold(backProject, 50, 255, cv2.THRESH_BINARY)
# 6)抠出目标图像中的感兴趣部分
thresh = cv2.merge((thresh, thresh, thresh))
res = cv2.bitwise_and(target, thresh)
# 展示图片
cv2.imshow("roi", roi)
cv2.imshow("target", target)
cv2.imshow("backProject", backProject)
cv2.imshow("thresh", thresh)
cv2.imshow("res", res)
cv2.waitKey(0)
cv2.destroyWindow()
直方图反向投影.png
网友评论