python绘制灰度直方图_python+opencv 灰度直方图及其二值化

本文介绍了如何使用Python和OpenCV进行灰度图像直方图绘制,包括图像的灰度直方图创建、三色折线图展示,以及全局和局部阈值二值化的方法,如Otsu算法、三角算法等。同时,讨论了在处理大图像时的二值化策略,并给出了实例代码。
摘要由CSDN通过智能技术生成

图像直方图(histogram)是图像的统计学特征,常用于了解图像的基本特征以便分析。不过图像的直方图不具有空间特征。

图像的灰度直方图(histogram),就是将图像转化成灰度图像之后,统计各个像素点的灰度值,绘制成直方图,其横轴是灰度值(0,255),纵轴是该灰度值所对应的像素的数目。对灰度直方图做积分=图像的size。

灰度直方图

1 defplt_hist(img):2 plt.hist(img.ravel(), 256, [0, 256])3 plt.show()

三色折线图(可以直观的看出三原色的占比分布)

1 defimg_hist(img):2 color = ("blue", "green", "red")3 for i, color inenumerate(color):4 hist = cv.calcHist([img], [i], None, [256], [0, 256])5 plt.plot(hist, color=color)6 plt.xlim([0, 25])7 plt.show()

一般来说,直方图有双峰性,会有两个峰值以区分前景和背景,但并不是每张图像都如此。分析图像的变化,进而确定最优二值化值。在两个峰值之间的最小值,经常是我们需要找的二值化值。我们可以发现,两个峰值之间的波谷是两个峰值的叠加区。有了灰度直方图,我们可以给图片做二值化。确定哪些pixel是我们需要关注的哪些是不重要的。二值化有两种主要形式:一种是全局阈值二值化,另外一种是局部阈值二值化。

选择二值化的值(找到两个双峰的最低点,但不是都有多峰可能存在多个最小值,可以用局部阈值)

经典算法:isodata algorithm 预设初始的二值化值,然后不断迭代,效果不是最好的

Otsu algorithm 研究双峰的关联性求二值化值

Entropy algorithm 熵算法,前景熵hb和背景熵hw。0-255个灰度值分别求熵,最大的h值就是我们要找的二值化值。

其他算法:triangle algorithm 灰度值的最大值和最左侧的最小值连接,然后做垂线,当垂线距离最大时,所对应的灰度值就是我们需要的二值化值,不过这个算法效果不是很好,应用于细胞分离比较多。

使用opencvAPI:(otsu和triangle)

1 defthreshold_binary(src):2 #把BGR图像转化成灰度图像

3 gray =cv.cvtColor(src, cv.COLOR_BGR2GRAY)4 #获得灰度直方图以便调整算法的使用

5 plt.hist(src.ravel(), 256, [0, 256])6 plt.show()7 #几种二值化方法

8 ret, binary = cv.threshold(gray, 50, 255, cv.THRESH_BINARY)#指定阈值50

9 print("二值阈值: %s" %ret)10 cv.imshow("threshold_binary", binary)11 ret_otsu, binary_otsu = cv.threshold(gray, 0, 255, cv.THRESH_BINARY |cv.THRESH_OTSU)12 print("二值阈值_otsu: %s" %ret_otsu)13 cv.imshow("threshold_binary_otsu", binary_otsu)14 ret_tri, binary_tri = cv.threshold(gray, 0, 255, cv.THRESH_BINARY |cv.THRESH_TRIANGLE)15 print("二值阈值_tri: %s" % ret_tri)

运行示例:

二值阈值: 50.0

二值阈值_otsu: 173.0

二值阈值_tri: 250.0

以上是全局阈值二值化的结果,下面还有局部阈值二值化。个人觉得局部阈值更好的描绘了图片的轮廓。

1 deflocal_threshold_binary(src):2 gray =cv.cvtColor(src, cv.COLOR_BGR2GRAY)3 binary_mean = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 25, 10)4 cv.imshow("binary_mean", binary_mean)5

6 binary_gau = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)7 cv.imshow("binary_gau", binary_gau)

两种方法,

超大图像及其二值化

经常会遇到一些比较大的图像,我们可以把图片拆分成很多个小方块分别进行全局二值化或者使用局部阈值。这时候可以用opencv处理图像显示不全,需要把图片保存到本地才行。

1 defbig_image_binary(src):2 print(src.shape)3 cw = 256

4 ch = 256

5 h, w, c =src.shape6 gray =cv.cvtColor(src, cv.COLOR_BGR2GRAY)7 for row inrange(0, h, ch):8 for col inrange(0, w, cw):9 roi = gray[row:row+ch, col:col+cw]10 dst = cv.adaptiveThreshold(roi, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)11 #ret_otsu, dst = cv.threshold(roi, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)

12 gray[row:row+ch, col:col+cw] =dst13 #计算方差和平均值,当这两个数值小于某一值时,可以认为图像为空白,做空白图像过滤

14 print(np.std(dst), np.mean(dst))15 cv.imwrite("E:/photo/big_img_binary.jpg", gray)

                   

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值