图像直方图及图像二值化常用算法原理总结

无意中看到一篇通过手机扫描可以分辨衣服的类型,文章写得挺神奇的,原理主要是通过直方图进行相似度匹配,本文就顺着这个思路查了很多资料并把这一类知识贯通了一下,也随便预习了一下以前学的OpenCV的相关知识。本文通过两个部分展现,第一部分,通过原始图片画图像直方图及直方图平滑过滤;第二部分,图像二值化算法原理总结。

第一部分,通过原始图片画图像直方图及直方图平滑过滤

函数1(OpenCV提供):calcHist—计算图像直方图

函数原型:calcHist(images, channels, mask, histSize, ranges, hist=None, accumulate=None)

images:图像矩阵,例如:[image]

channels:通道数,例如:0

mask:掩膜,一般为:None

histSize:直方图大小,一般等于灰度级数

ranges:横轴范围

 

函数2(OpenCV提供):equalizeHist—直方图均衡化

函数原型: equalizeHist(src, dst=None)

src:图像矩阵

dst:默认即可

 

函数3(Matplotlib提供):matplotlib.pyplot.hist直方图函数

matplotlib.pyplot.hist(x, bins=10, range=None, normed=False, weights=None, cumulative=False, bottom=None, histtype=u'bar', align=u'mid', orientation=u'vertical', rwidth=None, log=False, color=None, label=None, stacked=False, hold=None, **kwargs)

:  (n,) array or sequence of (n,) arrays

bins :  integer or array_like, optional

normed :  boolean, optional. If True, the first element of the return tuple will be the counts normalized to form a probability density, i.e.,n/(len(x)`dbin)

color :  color or array_like of colors or None, optional

 

函数4(OpenCV提供):blur—图像均值平滑滤波

函数原型:blur(src, ksize, dst=None, anchor=None, borderType=None)

src:图像矩阵

ksize:滤波窗口尺寸

 

函数5(OpenCV提供):GaussianBlur—图像高斯平滑滤波

函数原型:GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)

src:图像矩阵

ksize:滤波窗口尺寸

sigmaX:标准差

 

函数6(OpenCV提供):medianBlur—图像中值滤波

函数原型:medianBlur(src, ksize, dst=None)

src:图像矩阵

ksize:滤波窗口尺寸

 

函数7(OpenCV提供):bilateralFilter—图像双边滤波

函数原型:bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)

src:图像矩阵

d:邻域直径

sigmaColor:颜色标准差

sigmaSpace:空间标准差

 

Example1:通过OpenCVMatplotlib画出图像的直方图

# -*- coding: utf-8 -*-
import cv2
import matplotlib.pyplot as plt
# import a image
src = cv2.imread('../../image/girl.png')
# color histogram
chans = cv2.split(src)
colors = ("b","g","r")
# compute a image to hist by opencv
hist = cv2.calcHist([src], [0], None, [256], [0, 255])
# show some channel histogram image by opencv
plt.subplot(141),plt.plot(hist),plt.title('histogram by opencv'),plt.xlim([0,256])
# show all channel histogram image by opencv
for (chan,color) in zip(chans,colors):
hist = cv2.calcHist([chan],[0],None,[256],[0,256])
plt.subplot(142),plt.plot(hist,color = color),plt.title('Color Histogram by opencv')
plt.xlim([0,256])
# show all channel information histogram iamge by matplotlib
plt.subplot(143),plt.hist(src.ravel(),256),plt.title('histogram by matplotlib'),plt.xlim([0,256])
plt.show()

 

 

Example2:通过OpenCVMatplotlib画出基于Blur过滤后图像的直方图(图像均值平滑过滤)

# -*- coding: utf-8 -*-
import cv2
import matplotlib.pyplot as plt
# import a image
src = cv2.imread('../../image/girl.png')
# color histogram
chans = cv2.split(src)
colors = ("b","g","r")
# compute a image to hist by opencv
hist = cv2.calcHist([src], [0], None, [256], [0, 255])
# show some channel histogram image by opencv
plt.subplot(331),plt.plot(hist),plt.title('histogram by opencv with Original'),plt.xlim([0,256])
# show all channel histogram image by opencv
for (chan,color) in zip(chans,colors):
hist = cv2.calcHist([chan],[0],None,[256],[0,256])
plt.subplot(332),plt.plot(hist,color = color),plt.title('Color Histogram by opencv')
plt.xlim([0,256])
# show all channel information histogram iamge by matplotlib
plt.subplot(333),plt.hist(src.ravel(),256),plt.title('histogram by matplotlib'),plt.xlim([0,256])

blur_3 = cv2.blur(src,(3,3))   # 后面的滤波函数只需要修改改行即可
chans_3 = cv2.split(blur_3)
# compute a image to hist by opencv
hist_3 = cv2.calcHist([blur_3], [0], None, [256], [0, 255])
# show some channel histogram image by opencv
plt.subplot(334),plt.plot(hist_3),plt.title('hist blur 3 by opencv'),plt.xlim([0,256])
# show all channel histogram image by opencv
for (chans_3,color) in zip(chans,colors):
hist = cv2.calcHist([chans_3],[0],None,[256],[0,256])
plt.subplot(335),plt.plot(hist_3,color = color),plt.title('Color Hist by opencv')
plt.xlim([0,256])
# show all channel information histogram iamge by matplotlib
plt.subplot(336),plt.hist(blur_3.ravel(),256),plt.title('hist by matplotlib'),plt.xlim([0,256])

blur_7 = cv2.blur(src,(17,17))   # 后面的滤波函数只需要修改改行即可
chans_7 = cv2.split(blur_7)
# compute a image to hist by opencv
hist_7 = cv2.calcHist([blur_7], [0], None, [256], [0, 255])
# show some channel histogram image by opencv
plt.subplot(337),plt.plot(hist_7),plt.title('hist blur 17 by opencv'),plt.xlim([0,256])
# show all channel histogram image by opencv
for (chans_7,color) in zip(chans,colors):
hist = cv2.calcHist([chans_7],[0],None,[256],[0,256])
plt.subplot(338),plt.plot(hist_7,color = color),plt.title('Color Histogram by opencv')
plt.xlim([0,256])
# show all channel information histogram iamge by matplotlib
plt.subplot(339),plt.hist(blur_7.ravel(),256),plt.title('histogram by matplotlib'),plt.xlim([0,256])
plt.show()

 

Example3:通过OpenCVMatplotlib画出基于高斯过滤后图像的直方图

代码:类似Example2,讲过滤函数改成cv2.GaussianBlur(image,(3,3),0),其它一样。

结果图:

 

 

Example4:通过OpenCVMatplotlib画出基于中值滤波过滤后图像的直方图

代码:类似Example2,讲过滤函数改成cv2.medianBlur(image,3),其它一样。

结果图:

 

 

Example5:通过OpenCVMatplotlib画出基于双边滤波过滤后图像的直方图

代码:类似Example2,讲过滤函数改成cv2.bilateralFilter(image,5,21,21),其它一样。

结果图:

代码路径:E:\IdeaProjects_Python\faceprojects\imageProcessing\histogram

 

第二部分,图像二值化算法原理总结

图像二值化的目的是最大限度的将图象中感兴趣的部分保留下来,在很多情况下,也是进行图像分析、特征提取与模式识别之前的必要的图像预处理过程。这个看似简单的问题,在过去的四十年里受到国内外学者的广泛关注,产生了数以百计的阈值选取方法,但如同其他图像分割算法一样,没有一个现有方法对各种各样的图像都能得到令人满意的结果。

在这些庞大的分类方法中,基于直方图的全局二值算法占有了绝对的市场份额,这些算法都从不同的科学层次提出了各自的实施方案,并且这类方法都有着一些共同的特点:简单、算法容易实现、执行速度快。

一:灰度平局值值法:

描述:即使用整幅图像的灰度平均值作为二值化的阈值,一般该方法可作为其他方法的初始猜想值。

二、百分比阈值(P-Tile法)

描述:Doyle于1962年提出的P-Tile (即P分位数法)可以说是最古老的一种阈值选取方法。该方法根据先验概率来设定阈值,使得二值化后的目标或背景像素比例等于先验概率,该方法简单高效,但是对于先验概率难于估计的图像却无能为力。

 三、基于谷底最小值的阈值

描述:此方法实用于具有明显双峰直方图的图像,其寻找双峰的谷底作为阈值,但是该方法不一定能获得阈值,对于那些具有平坦的直方图或单峰图像,该方法不合适。

实现过程:该函数的实现是一个迭代的过程,每次处理前对直方图数据进行判断,看其是否已经是一个双峰的直方图,如果不是,则对直方图数据进行半径为1(窗口大小为3)的平滑,如果迭代了一定的数量比如1000次后仍未获得一个双峰的直方图,则函数执行失败,如成功获得,则最终阈值取两个双峰之间的谷底值作为阈值。

注意在编码过程中,平滑的处理需要当前像素之前的信息,因此需要对平滑前的数据进行一个备份。另外,首数据类型精度限制,不应用整形的直方图数据,必须转换为浮点类型数据来进行处理,否则得不到正确的结果。

该算法相关参考论文如下:

J. M. S. Prewitt and M. L. Mendelsohn, "The analysis of cell images," innnals of the New York Academy of Sciences, vol. 128, pp. 1035-1053, 1966.
C. A. Glasbey, "An analysis of histogram-based thresholding algorithms," CVGIP: Graphical Models and Image Processing, vol. 55, pp. 532-537, 1993.

 

四、基于双峰平均值的阈值

描述:该算法和基于谷底最小值的阈值方法类似,只是最后一步不是取得双峰之间的谷底值,而是取双峰的平均值作为阈值。

 

五、迭代最佳阈值

描述:该算法先假定一个阈值,然后计算在该阈值下的前景和背景的中心值,当前景和背景中心值得平均值和假定的阈值相同时,则迭代中止,并以此值为阈值进行二值化。

 

六、OSTU大律法

描述:该算法是1979年由日本大津提出的,主要是思想是取某个阈值,使得前景和背景两类的类间方差最大,matlab中的graythresh即是以该算法为原理执行的。

特点:该算法对于那些具有平坦的直方图的图像具有一定的适应能力。

 

、一维最大熵

描述:该算法把信息论中熵的概念引入到图像中,通过计算阈值分割后两部分熵的和来判断阈值是否为最佳阈值。

 

八、力矩保持法 

描述:该算法通过选择恰当的阈值从而使得二值后的图像和原始的灰度图像具有三个相同的初始力矩值。

参考论文:W. Tsai, “Moment-preserving thresholding: a new approach,” Comput.Vision Graphics Image Process., vol. 29, pp. 377-393, 1985.

 

 九、基于模糊集理论的阈值

该算法的具体分析可见:基于模糊集理论的一种图像二值化算法的原理、实现效果及代码

特点:此法也借用香农熵的概念,该算法一般都能获得较为理想的分割效果,不管是对双峰的还是单峰的图像。

十、Kittler最小错误分类法

  • Kittler, J & Illingworth, J (1986), "Minimum error thresholding", Pattern Recognition19: 41-47

十一:ISODATA(也叫做intermeans法)

  参考论文:Ridler, TW & Calvard, S (1978), "Picture thresholding using an iterative selection method", IEEE Transactions on Systems, Man and Cybernetics 8: 630-632, <http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=4310039>

 

 

参考资料:

资料1(用直方图做相似度匹配的高端套路(英文)):

http://download.csdn.net/download/qq404752007/9512900

资料2(对论文Shape-context.pdf进行简单的通俗化阐述):

http://blog.csdn.net/qq404752007/article/details/51339281

资料3(OpenCV函数索引):

http://docs.opencv.org/3.3.0/globals_func_c.html#index_c

资料4(ImageJ):

http://imagej.net/Auto_Threshold

资料5(十三种基于直方图的图像全局二值化算法原理、实现、代码及效果):

http://www.cnblogs.com/Imageshop/p/3307308.html

资料6(基于模糊集理论的一种图像二值化算法的原理、实现效果及代码):

http://www.cnblogs.com/Imageshop/p/3302850.html

资料7(OpenCV之基本的图像操作函数使用及案例):

https://www.sharebook.site/articles/opencv-basic-images-operations/

资料8(Opencv之图像阈值分割函数的使用及Demo分析):

https://www.sharebook.site/articles/opencv-image-thresholding/

资料9(Opencv之图像滤波与图像形态变换):

https://www.sharebook.site/articles/opencv-smoothing-imagess-and-morphological-transformations/

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: