# OpenCV系列之图像阈值 | 十五

• 在本教程中，您将学习简单阈值，自适应阈值和Otsu阈值。

### 简单阈值

• cv.THRESH_BINARY
• cv.THRESH_BINARY_INV
• cv.THRESH_TRUNC
• cv.THRESH_TOZERO
• cv.THRESH_TOZERO_INV

```import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
ret,thresh1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
ret,thresh2 = cv.threshold(img,127,255,cv.THRESH_BINARY_INV)
ret,thresh3 = cv.threshold(img,127,255,cv.THRESH_TRUNC)
ret,thresh4 = cv.threshold(img,127,255,cv.THRESH_TOZERO)
ret,thresh5 = cv.threshold(img,127,255,cv.THRESH_TOZERO_INV)
titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in xrange(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()```

### 自适应阈值

BLOCKSIZE确定附近区域的大小，C是从邻域像素的平均或加权总和中减去的一个常数。

### Otsu的二值化

```import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 全局阈值
ret1,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
# Otsu阈值
ret2,th2 = cv.threshold(img,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
# 高斯滤波后再采用Otsu阈值
blur = cv.GaussianBlur(img,(5,5),0)
ret3,th3 = cv.threshold(blur,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
# 绘制所有图像及其直方图
images = [img, 0, th1,
img, 0, th2,
blur, 0, th3]
titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)',
'Original Noisy Image','Histogram',"Otsu's Thresholding",
'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]
for i in xrange(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()```

#### Otsu的二值化如何实现？

```img = cv.imread('noisy2.png',0)
blur = cv.GaussianBlur(img,(5,5),0)
# 寻找归一化直方图和对应的累积分布函数
hist = cv.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 xrange(1,256):
p1,p2 = np.hsplit(hist_norm,[i]) # 概率
q1,q2 = Q[i],Q[255]-Q[i] # 对类求和
b1,b2 = np.hsplit(bins,[i]) # 权重
# 寻找均值和方差
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
# 计算最小化函数
fn = v1*q1 + v2*q2
if fn < fn_min:
fn_min = fn
thresh = i
# 使用OpenCV函数找到otsu的阈值
ret, otsu = cv.threshold(blur,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
print( "{} {}".format(thresh,ret) )
```

### 其他资源

1.Digital Image Processing, Rafael C. Gonzalez

### 练习题

1.Otsu的二值化有一些优化。您可以搜索并实现它。

0 条评论

• ### OpenCV系列之图像的几何变换 | 十四

OpenCV提供了两个转换函数cv.warpAffine和cv.warpPerspective，您可以使用它们进行各种转换。cv.warpAffine采用2x3...

• ### OpenCV系列之傅里叶变换 | 三十

傅立叶变换用于分析各种滤波器的频率特性。对于图像，使用2D离散傅里叶变换(DFT)查找频域。一种称为快速傅立叶变换(FFT)的快速算法用于DFT的计算。关于这些...

• ### OpenCV系列之轮廓特征 | 二十二

特征矩可以帮助您计算一些特征，例如物体的质心，物体的面积等。请查看特征矩上的维基百科页面。函数cv.moments()提供了所有计算出的矩值的字典。见下文：

• ### ViewAnimationUtils实现揭露动画

以上效果就是通过ViewAnimationUtils实现的，利用简单的几行代码，实现酷炫的揭露动画。

• ### (二十六) 初遇python OOP面向对象编程-类方法和静态方法

各位读者大大们大家好，今天学习python的面向对象编程-类方法和静态方法，并记录学习过程欢迎大家一起交流分享。

• ### 云服务器网络性能影响因素分析

目前我们在公有云上买到的服务器，一般网卡类型都是virtio，这个可以通过ethtool -i eth1获取。

• ### python实现 opencv 学习笔记 图像二值化

上一遍记录了当时集群资源死锁的问题，后来想了想其实小文件较多也会让集群变慢，小文件较多在执行作业时rpc时间就会增加，从而拖垮了job的执行速度。

• ### 2D图像中点的旋转

点的逆时针旋转可以看做是以原点为起点的向量绕原点逆时针旋转；更进一步，保持向量不动，让坐标轴顺时针旋转θ。