opencv-python教程学习系列12-图像阈值
前言
opencv-python教程学习系列记录学习python-opencv过程的点滴,本文主要介绍图像阈值/二值化,坚持学习,共同进步。
系列教程参照OpenCV-Python中文教程;
系统环境
系统:win7_x64;
python版本:python3.5.2;
opencv版本:opencv3.3.1;
内容安排
1.知识点介绍;
2.测试代码;
具体内容
1.知识点介绍;
图像的阈值处理一般使得图像的像素值更单一、图像更简单。阈值可以分为全局性质的阈值,也可以分为局部性质的阈值,可以是单阈值的也可以是多阈值的。当然阈值越多是越复杂的。下面将介绍opencv下的三种阈值方法。主要涉及的函数是cv2.threshold , cv2.adaptiveThreshold;
1.1 简单阈值;
简单阈值当然是最简单,选取一个全局阈值,然后把整幅图像分成了非黑即白的二值图像。
使用的函数是cv2.threshold,包括四个参数,第一个是原图像(灰度图像),第二个是进行分类的阈值,第三个是高于(低于)阈值时赋予的新值,第四个是一个方法选择参数,常用的方法有:
• cv2.THRESH_BINARY(黑白二值)
• cv2.THRESH_BINARY_INV(黑白二值反转)
• cv2.THRESH_TRUNC (得到的图像为多像素值)
• cv2.THRESH_TOZERO
• cv2.THRESH_TOZERO_INV
该函数有两个返回值,第一个retVal(得到的分割阈值),第二个就是阈值化后的图像。
1 | ret , thresh5 = cv2.threshold(img, 127 , 255 ,cv2.THRESH_TOZERO_INV) |
1.2 自适应阈值;
自适应阈值可以看成一种局部性的阈值,通过规定一个区域大小,比较这个点与区域大小里面像素点的平均值(或者其他特征)的大小关系确定这个像素点是属于黑或者白(如果是二值情况)。使用的函数为cv2.adaptiveThreshold,该函数有6个参数,分别是原始灰度图像、像素值上限、自适应方法、赋值方法、邻域大小、常数,其中自适应方法包含cv2.ADAPTIVE_THRESH_MEAN_C (邻域均值)和cv2.ADAPTIVE_THRESH_GAUSSIAN_C(邻域加权和)两种,常数表示阈值等于均值或者加权值减去这个常数;
1 2 3 | ret , th1 = cv2.threshold(img, 127 , 255 ,cv2.THRESH_BINARY) # 11为block size,2为C值 th2 = cv2.adaptiveThreshold(img, 255 ,cv2.ADAPTIVE_THRESH_MEAN_C , cv2.THRESH_BINARY, 11 , 2 ) |
1.3 大津法OTSU;
Otsu方法试图自动找到一个最好的阈值,可以最小化加权的类内方差,并且Otsu非常适合于图像灰度直方图具有双峰的情况,在双峰(bimodal )之间找到一个值作为阈值,对于非双峰图像,可能并不是很好用。
1 | ret2,th2 = cv2.threshold(img, 0 , 255 ,cv2.THRESH_BINARY + cv2.THRESH_OTSU) |
2.测试代码;
2.1 自适应阈值;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread( 'test.jpg' , 0 ) #中值滤波 img = cv2.medianBlur(img, 5 ) ret , th1 = cv2.threshold(img, 127 , 255 ,cv2.THRESH_BINARY) # 11为block size,2为C值 th2 = cv2.adaptiveThreshold(img, 255 ,cv2.ADAPTIVE_THRESH_MEAN_C , cv2.THRESH_BINARY, 11 , 2 ) th3 = cv2.adaptiveThreshold(img, 255 ,cv2.ADAPTIVE_THRESH_GAUSSIAN_C , cv2.THRESH_BINARY, 11 , 2 ) titles = [ 'original image' , 'global thresholding (v=127)' , 'Adaptive mean thresholding' , 'adaptive gaussian thresholding' ] images = [img,th1,th2,th3] for i in range ( 4 ): plt.subplot( 2 , 2 ,i + 1 ),plt.imshow(images[i], 'gray' ) plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show() |
2.2 OTSU方法;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread( 'test.jpg' , 0 ) ret1,th1 = cv2.threshold(img, 127 , 255 ,cv2.THRESH_BINARY) ret2,th2 = cv2.threshold(img, 0 , 255 ,cv2.THRESH_BINARY + cv2.THRESH_OTSU) #(5,5)为高斯核的大小,0为标准差 blur = cv2.GaussianBlur(img,( 5 , 5 ), 0 ) #高斯滤波平滑 #阀值一定要设为0 ret3,th3 = cv2.threshold(blur, 0 , 255 ,cv2.THRESH_BINARY + cv2.THRESH_OTSU) images = [img, 0 ,th1, img, 0 ,th2, img, 0 ,th3] titles = [ 'original noisy image' , 'histogram' , 'global thresholding(v=127)' , 'original noisy image' , 'histogram' , "otsu's thresholding" , 'gaussian filtered image' , 'histogram' , "otus's thresholding" ] #这里使用了pyplot中画直方图的方法,plt.hist要注意的是他的参数是一维数组 #所以这里使用了(numpy)ravel方法,将多维数组转换成一维,也可以使用flatten方法 for i in range ( 3 ): plt.subplot( 3 , 3 ,i * 3 + 1 ),plt.imshow(images[i * 3 ], 'gray' ) plt.title(titles[i * 3 ]),plt.xticks([]),plt.yticks([]) plt.subplot( 3 , 3 ,i * 3 + 2 ),plt.hist(images[i * 3 ].ravel(), 256 ) plt.title(titles[i * 3 + 1 ]),plt.xticks([]),plt.yticks([]) plt.subplot( 3 , 3 ,i * 3 + 3 ),plt.imshow(images[i * 3 + 2 ], 'gray' ) plt.title(titles[i * 3 + 2 ]),plt.xticks([]),plt.yticks([]) plt.show() |
2.3 OTSU的实现;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #opencv官网https://docs.opencv.org/3.3.1/d7/d4d/tutorial_py_thresholding.html import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread( 'test.jpg' , 0 ) blur = cv2.GaussianBlur(img,( 5 , 5 ), 0 ) # find normalized_histogram, and its cumulative distribution function hist = cv2.calcHist([blur],[ 0 ], None ,[ 256 ],[ 0 , 256 ]) hist_norm = hist.ravel() / hist. max () Q = hist_norm.cumsum() bins = np.arange( 256 ) fn_min = np.inf thresh = - 1 for i in range ( 1 , 256 ): p1,p2 = np.hsplit(hist_norm,[i]) # probabilities q1,q2 = Q[i],Q[ 255 ] - Q[i] # cum sum of classes b1,b2 = np.hsplit(bins,[i]) # weights # finding means and variances m1,m2 = np. sum (p1 * b1) / q1, np. sum (p2 * b2) / q2 v1,v2 = np. sum (((b1 - m1) * * 2 ) * p1) / q1,np. sum (((b2 - m2) * * 2 ) * p2) / q2 # calculates the minimization function fn = v1 * q1 + v2 * q2 if fn < fn_min: fn_min = fn thresh = i # find otsu's threshold value with OpenCV function ret, otsu = cv2.threshold(blur, 0 , 255 ,cv2.THRESH_BINARY + cv2.THRESH_OTSU) print ( "{} {}" . format (thresh,ret) ) #ret表示得到的分割阈值; |
参考
1.图像阈值;
2.CSDN图像阈值;
3.opencv官网;
完
心正意诚,做自己该做的事情,做自己喜欢做的事情,安静做一枚有思想的技术媛。
版权声明,转载请注明出处:https://www.cnblogs.com/happyamyhope/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】