opencv直方图绘制详解

简介: opencv直方图绘制详解

1.直方图的定义、意义和特征

1. 定义

在统计学中,直方图是一种对数据分布情况的图形表示,是一种二维统计图表,

他的两个坐标分别是统计样本(图像、视频帧)和样本的某种属性(亮度,像素值,梯度,方向,色彩等等任何特征)

2. 意义

(1)直方图是图像中像素强度分布的图形表达方式。

(2)直方图统计了每一个强度值所具有的像素个数。

3. 特征

(1)直方图不再表征任何的图像纹理信息,而是对图像像素的统计。

(2)由于同一物体无论是旋转还是平移在图像中都具有相同的灰度值,因此直方图具有平移不变性、放缩不变性等优点。

4. 方法和参数

cv2.calcHist(images, channels, mask, histSize, ranges[hist[, accumulate]])

(1)images : 整型类型(uint8和float32)的原图(list或tuple形式的输入)。

(2)channels : 通道的索引,例如:[0]代表灰度图片,[0],[1],[2]代表多通道,list或tuple形式的输入。

(3)mask : 计算图片指定区域的直方图。如果mask为none,那么计算整张图。

(4)histSize( bins ) : 每个色调值(范围: 0 ~ 255)对应的像素数量/频率。[这256个值中的每一个都被称为bin,它的取值有8,16,32,64,128,256。在OpenCV中,用histSize表示bins。],list或tuple形式的输入

(5)range : 强度值的范围,[0, 256]。

cv2.calcHist()函数的返回值

对于hist = cv2.calcHist([img],[0],None,[256],[0,256])中,hist是一个256*1的矩阵,每一个值代表了每个灰度值对应的像素点数目

print(type(hist))

<class ‘numpy.ndarray’>

输出的结果表示这是一个多维数组

print(hist)

[[1.000e+00]

[0.000e+00]

[2.000e+00]

[0.000e+00]

[2.010e+02]

[2.180e+02]

[2.160e+02]

[2.660e+02]

[3.350e+02]

[3.110e+02]

[4.670e+02]]

经计算,共有256个值,即可以输出hist[0]到hist[255]。整个hist[i]则表示灰度值

print(hist[175],hist[255])

[3181.] [467.]

通过直方图可看出输出的结果就是每一个灰度值对应的像素数目,横坐标是bins区间值,纵坐标是每个bins的像素数目

2.灰度直方图

# 1 导入库
import cv2
import matplotlib.pyplot as plt
import numpy as np

# 2 方法:显示图片
def show_image(image, title, pos):
    #  顺序转换:BGR TO RGB
    #height和width是不变的,channel倒序输出
    image_RGB = image[:, :, ::-1] # shape : (height, width, channel)
    # 显示标题
    plt.title(title)
    plt.subplot(2, 3, pos) # 定位
    plt.imshow(image_RGB)

# 3 方法:显示图片的灰度直方图
def show_histogram(hist, title, pos, color):
    # 显示标题
    plt.title(title)
    plt.subplot(2, 3, pos) # 定位图片
    plt.xlabel("Bins") # 横轴信息
    plt.ylabel("Pixels") # 纵轴信息
    plt.xlim([0, 256]) # 范围
    plt.plot(hist, color=color) # 绘制直方图


# 4 主函数 main()
def main():
    # 5 创建画布
    plt.figure(figsize=(15, 6)) # 画布大小
    #设置标题,给画布添加标题
    plt.suptitle("Gray Image Histogram", fontsize=14, fontweight="bold") # 设置标题形式

    # 6 加载图片
    img = cv2.imread("children.jpg")

    # 7 灰度转换
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 8 计算灰度图的直方图
    hist_img = cv2.calcHist([img_gray], [0], None, [256], [0, 256])

    # 9 展示灰度直方图
    # 灰度图转换成BGR格式图片
    img_BGR = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR)
    show_image(img_BGR, "BGR image", 1)
    show_histogram(hist_img, "gray image histogram", 4, "m")

    plt.show()

if __name__ == '__main__':
    main()

运行结果

c0ef410837df439191a705c02186cc3a.png


设置画布标题函数介绍

matplotlib.pyplot.suptitle(t,x=0.5,y=0.98,horizontalalignment=‘center’,verticalalignment=‘top’, fontsize=‘large’,

fontweight=‘normal’, **kwargs)

参数 含义

灰度直方图进阶

对图像像素添加或减少展示

代码:

# 1 导入库
import cv2
import matplotlib.pyplot as plt
import numpy as np

# 2 方法:显示图片
def show_image(image, title, pos):
    #  顺序转换:BGR TO RGB
    image_RGB = image[:, :, ::-1] # shape : (height, width, channel)
    # 显示标题
    plt.title(title)
    plt.subplot(2, 3, pos) # 定位
    plt.imshow(image_RGB)

# 3 方法:显示图片的灰度直方图
def show_histogram(hist, title, pos, color):
    # 显示标题
    plt.title(title)
    plt.subplot(2, 3, pos) # 定位图片
    plt.xlabel("Bins") # 横轴信息
    plt.ylabel("Pixels") # 纵轴信息
    plt.xlim([0, 256]) # 范围
    plt.plot(hist, color=color) # 绘制直方图


# 4 主函数 main()
def main():
    # 5 创建画布
    plt.figure(figsize=(15, 6)) # 画布大小
    plt.suptitle("Gray Image Histogram", fontsize=14, fontweight="bold") # 设置标题形式

    # 6 加载图片
    img = cv2.imread("children.jpg")

    # 7 灰度转换
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 8 计算灰度图的直方图
    hist_img = cv2.calcHist([img_gray], [0], None, [256], [0, 256])

    # 9 展示灰度直方图
    # 灰度图转换成BGR格式图片
    img_BGR = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR)
    show_image(img_BGR, "BGR image", 1)
    show_histogram(hist_img, "gray image histogram", 4, "m")

    # 10 对图片中的每个像素值增加50个像素
    M = np.ones(img_gray.shape, np.uint8) * 50 # 构建矩阵

    #使用cv2.add()方法进行相加减
    added_img = cv2.add(img_gray, M)
    add_img_hist = cv2.calcHist([added_img], [0], None, [256], [0, 256]) # 计算直方图
    added_img_BGR = cv2.cvtColor(added_img, cv2.COLOR_GRAY2BGR)
    show_image(added_img_BGR, "added image", 2)
    show_histogram(add_img_hist, "added image hist", 5, "m")

    # 11 对图片中的每个像素值减去50个像素
    subtract_img = cv2.subtract(img_gray, M)
    subtract_img_hist = cv2.calcHist([subtract_img], [0], None, [256], [0, 256]) # 计算直方图
    subtract_img_BGR = cv2.cvtColor(subtract_img, cv2.COLOR_GRAY2BGR)
    show_image(subtract_img_BGR, "subtracted image", 3)
    show_histogram(subtract_img_hist, "subtracted image hist", 6, "m")

    plt.show()

if __name__ == '__main__':
    main()

可以看到增加了50像素的图片变亮,减少了50个像素的变暗

3.mask详解

mask : 提取感兴趣区域。

如下图,设置了mask区域被显示出来,其他区域被覆盖

实战

# 1 导入库
import cv2
import matplotlib.pyplot as plt
import numpy as np

# 2 方法:显示图片
def show_image(image, title, pos):
    img_RGB = image[:, :, ::-1] # BGR to RGB
    plt.title(title)
    plt.subplot(2, 2, pos)
    plt.imshow(img_RGB)

# 3 方法:显示灰度直方图
def show_histogram(hist, title, pos, color):
    plt.subplot(2, 2, pos)
    plt.title(title)
    plt.xlim([0, 256])
    plt.plot(hist, color=color)

# 4 主函数
def main():
    # 5 创建画布
    plt.figure(figsize=(12, 7))
    plt.suptitle("Gray Image and Histogram with mask", fontsize=14, fontweight="bold")

    # 6 读取图片并灰度转换,计算直方图,显示
    img_gray = cv2.imread("children.jpg", 0) # 读取并进行灰度转换
    img_gray_hist = cv2.calcHist([img_gray], [0], None, [256], [0, 256]) # 计算直方图
    # 灰度图转换成BGR格式图片
    img_BGR = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR)
    show_image(img_BGR, "BGR image", 1)
    # show_image(img_gray, "image gray", 1)
    show_histogram(img_gray_hist, "image gray histogram", 2, "m")

    # 7 创建mask,计算位图,直方图
    mask = np.zeros(img_gray.shape[:2], np.uint8)
    #截取mask区域
    mask[130:500, 400:1400] = 255 # 获取mask,并赋予颜色
    img_mask_hist = cv2.calcHist([img_gray], [0], mask, [256], [0, 256]) # 计算mask的直方图,这里的mask直接写上即可,不要写成mask=mask

    # 8 通过位运算(与预算)计算带有mask的灰度图片
    mask_img = cv2.bitwise_and(img_gray, img_gray, mask = mask)   #这里的mask一定要写成mask=mask,否则无法实现mask功能
    #将灰色图片转换成BGR格式图片
    mask_BGR =  cv2.cvtColor(mask_img, cv2.COLOR_GRAY2BGR)
    # 9 显示带有mask的图片和直方图
    show_image(mask_BGR, "gray image with mask", 3)
    show_histogram(img_mask_hist, "histogram with masked gray image", 4, "m")

    plt.show()
if __name__ == '__main__':
    main()

可以看到mask显示出来

4.彩色直方图

记住三点:

(1)直方图是图像中像素强度分布。

(2)直方图统计了每一个强度值所具有的像素个数。

(3)cv2.calcHist(images, channels, mask, histSize, ranges)

代码

# 1 导入库
import cv2
import matplotlib.pyplot as plt
import numpy as np

# 2 方法:显示图片
def show_image(image, title, pos):
    plt.subplot(3, 2, pos)
    plt.title(title)
    image_RGB = image[:, :, ::-1] # BGR to RGB
    plt.imshow(image_RGB)
    #关闭坐标轴
    plt.axis("off")

# 3 方法:显示彩色直方图 b, g, r
def show_histogram(hist, title, pos, color):
    plt.subplot(3, 2, pos)
    plt.title(title)
    plt.xlim([0, 256])
    #灰度只有一种颜色,彩色直方图是有三个通道的,RGB都要绘制出来,需要用循环来分别显示
    for h, c in zip(hist, color): # color: ('b', 'g', 'r')
        plt.plot(h, color=c)


# 4 方法:计算直方图,每个通道都要计算
def calc_color_hist(image):
    # b, g, r
    hist = []
    hist.append( cv2.calcHist([image], [0], None, [256], [0, 256]))
    hist.append( cv2.calcHist([image], [1], None, [256], [0, 256]))
    hist.append( cv2.calcHist([image], [2], None, [256], [0, 256]))
    return hist

# 5 主函数
def main():
    # 5.1 创建画布
    plt.figure(figsize=(12, 8))
    plt.suptitle("Color Histogram", fontsize=14, fontweight="bold")

    # 5.2 读取原图片
    img = cv2.imread("children.jpg")

    # 5.3 计算直方图
    img_hist = calc_color_hist(img)

    # 5.4 显示图片和直方图
    show_image(img, "RGB Image", 1)
    #彩色的,传颜色,必须传进去三个通道
    show_histogram(img_hist, "RGB Image Hist", 2, ('b', 'g', 'r'))

   
    # 5.5 原始图片中的每个像素增加50个像素值
    M = np.ones(img.shape, dtype="uint8") * 50

    added_image = cv2.add(img, M) # 像素一一对应相加
    added_image_hist = calc_color_hist(added_image)
    show_image(added_image, 'added image', 3)
    show_histogram(added_image_hist, 'added image hist', 4, ('b', 'g', 'r'))


   
    # 5.6 原始图片中的每个像素减去50个像素值
    subtracted_image = cv2.subtract(img, M)
    subtracted_image_hist = calc_color_hist(subtracted_image)
    show_image(subtracted_image, 'subtracted image', 5)
    show_histogram(subtracted_image_hist, 'subtracted image hist', 6, ('b', 'g', 'r'))

    plt.show()
if __name__ == '__main__':
    main()

可见,绘制出了原始图片,加强像素,减小像素后的图片和彩色直方图

注意:彩色直方图与灰度直方图绘制基本相同,最大区别在于,彩色直方图绘制需要将三个通道色彩全部绘制出来

相关文章
|
9月前
|
C++
OpenCV-绘制简易直方图DrawHistImg
OpenCV-绘制简易直方图DrawHistImg
|
1月前
|
计算机视觉
OpenCV中的二维直方图
【6月更文挑战第12天】中的二维直方图。
12 1
|
29天前
|
算法 计算机视觉
【Qt&OpenCV 直方图计算 split/calcHist/normalize】
【Qt&OpenCV 直方图计算 split/calcHist/normalize】
18 0
|
2月前
|
计算机视觉 索引
【OpenCV】- 直方图反向投影
【OpenCV】- 直方图反向投影
|
2月前
|
计算机视觉 索引
【OpenCV】直方图计算 & 均衡化直方图
【OpenCV】直方图计算 & 均衡化直方图
|
2月前
|
算法 计算机视觉
OpenCV直方图
OpenCV直方图
20 0
|
2月前
|
算法 Serverless 计算机视觉
opencv 直方图处理(python)
opencv 直方图处理(python)
|
2月前
|
存储 数据可视化 Serverless
OpenCV(十八):图像直方图
OpenCV(十八):图像直方图
51 0
|
8月前
|
计算机视觉
用openCV做统计直方图
用openCV做统计直方图
28 0
|
11月前
|
算法 安全 机器人
Baumer工业相机堡盟工业相机如何联合BGAPISDK和OpenCV实现图像的直方图算法增强(C++)
Baumer工业相机堡盟工业相机如何联合BGAPISDK和OpenCV实现图像的直方图算法增强(C++)
50 0