python图像直方图、获取每一个柱的个数,OpenCV-Python学习(十一):直方图

目录:

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

你可能感兴趣的:(python图像直方图,获取每一个柱的个数)