绘制图像灰度直方图——将图像的灰度分布可视化方法总结

        今天在实现图像阈值分割的时候,需要找到能将背景与物体区分开的灰度阈值,因为处理到的图像比较简单,它的直方图具有一个十分明显的特点,也就是它的直方图以双峰一谷的形式呈现,将物体与背景区分开来的阈值也就是谷所对应的阈值,利用数学概念解释一下,双峰就对应着两个极大值,谷对应着极小值,也就是在两个极大值之间找到这个最小值,当然也可以通过统计一下图像灰度值的分布,将灰度值分布以可视化的方式呈现,然后找到合适的阈值,这比排序找极小值的效率快很多,在这里我将介绍三种将灰度分布可视化的方式。

        方法一————利用matplotlib库中的hist()函数

matplotlib.pyplot.hist(xbins=Nonerange=Nonedensity=Falseweights=Nonecumulative=Falsebottom=Nonehisttype='bar'align='mid'orientation='vertical'rwidth=Nonelog=Falsecolor=Nonelabel=Nonestacked=False*data=None**kwargs)

一般只定义前面三个参数:

x: 输入的数据

bins:如果bins输入的是一个整数,那么它代表着在输出的图像中,横坐标被均分为多少份

range:它定义了横坐标的范围,输入的是存储了两个数的列表,左边的数是横坐标起点,右边的数是横坐标截止点

这个函数输出的最终结果,是显示每一个灰度值,以及其对应的频率的连续图 

        方法二————利用opencv中的calcHist函数

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

 image:需要被统计灰度值分布的图像,有一个血的教训,image一定要用[]框住

channels:图像通道,对于一个BGR图像, [0], [1],[2]分别对于B,G,R三个通道

mask:一般默认其为None即可

histSize:定义了直方图横坐标范围

ranges:定义了横坐标被分为多少份

        方法三————利用PLotly进行可视化绘图

Plotly生成的图表是交互式的,也就是说当你用鼠标指向对应的一个灰度值时,他会直接显示这个灰度值的频率,但是耗时比较长,应为他需要用程序计算出每个灰度值对应的频数是多少。

        在这里主要用到了:

        Bar函数,来存储输入数据的横纵坐标

        Layout函数,用来定义函数的标题,横纵坐标

        offline.plot, 最终的绘图

三种方法的实现过程总程序如下:

import cv2
import matplotlib.pyplot as plt
from plotly import offline
from  plotly.graph_objs import Bar, Layout
img_source = cv2.imread('C:\\Users\\yu\\Desktop\\picture_csdn\\cells_segmentation.jpg', cv2.IMREAD_COLOR)
img_gray = cv2.cvtColor(img_source, cv2.COLOR_BGR2GRAY)
cv2.imshow('img_gray', img_gray)
#   方法二————利用opencv中的calcHist函数
img_hist = cv2.calcHist([img_gray], [0], None, [256], [0, 256])
plt.plot(img_hist, color='blue')
plt.show()
#   方法一————利用matplotlib库中的hist()函数
plt.hist(img_gray.ravel(), 256, [0, 256])#ravel函数功能是将多维数组降为一维数组
plt.show()
ret, img_segmentation = cv2.threshold(img_gray, 80, 255, cv2.THRESH_TRUNC)#    对图像进行阈值分割
cv2.imshow('img_segmentation', img_segmentation)#    图像分割结果
#    方法三————利用PLotly进行可视化绘图
a_input = list(img_gray.ravel())
frequencies = []
for value in list(range(0, 256)):
    print(value)
    frequency = a_input.count(value)
    frequencies.append(frequency)
#   对结果可视化
x_values = list(range(0, 256))
data = [Bar(x=x_values, y=frequencies)]
x_axis_config = {'title': '灰度值'}
y_axis_config = {'title': '灰度值的频率'}
my_layout = Layout(title='一个图像的灰度直方图', xaxis=x_axis_config, yaxis=y_axis_config)
offline.plot({'data': data, 'layout': my_layout}, filename='gray_histogram.html')
cv2.waitKey(0)
cv2.destroyAllWindows()

   在上面的程序中,附带了一个我对图像进行阈值分割的两条代码,读者在使用程序的时候可以将其注释掉。

在这里我统计的图像是一个将彩色图像转化为灰度图像的细胞图像:

 三种灰度直方分布结果如下所示:

方法一

方法二

方法三

猜你喜欢

转载自blog.csdn.net/kuwola/article/details/122546479