• 简单阈值,自适应阈值,Otsu's二值化等

1.简单阈值

  当像素值高于阈值时,我们给这个像素赋予一个新值,否则给他赋予另一个值。这个函数就是cv2.threshhold()。这个函数的第一个参数就是原图像,一般是灰度图(貌似非灰度图也可以)。第二个参数就是用来对像素值进行分类的阈值。第三个参数就是当像素值高于阈值时应该被赋予的新像素值。(之前在设置掩码的时候已经提过这个函数了)

OpenCV提供了多种不同的阈值方法,这是第四个参数。这些方法包括:

  • cv2.THRESH_BINARY
  • cv2.THRESH_BINARY_INV
  • cv2.THRESH_TRUNC
  • cv2.THRESH_TOZERO
  • cv2.THRESH_TOZERO_INV

具体效果如下:

最常用的一般是第一个。

该函数有两个返回值,第一个是retVal(后面会涉及),第二是阈值化后的图像。例程如下:

# -*- coding:utf-8 -*-

import numpy as np
import  cv2
from matplotlib import pyplot as plt

img = cv2.imread('2.jpg',0)
ret,thresh1=cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret,thresh2=cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3=cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4=cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,thresh5=cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)

titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2,
thresh3, thresh4, thresh5]

#pyplot的绘图方法
for i in range(6):
    plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

plt.show()

效果如下:

教材上的例子感觉更明白一点:

2.自适应阈值

  在前面部分我们使用的是全局阈值,整幅图采用同一个数当做阈值。但这种方法并不适用于所有情况,尤其是当同一副图像上的不同部分的具有不同的亮度的。这时我们可以采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一副图像上的不同的区域采用的し不同
阈值,从而し我们能在亮度不同时得到更好的结果。

  这种方法需要我们指定三个参数,返回值只有一个:

  • Adaptive
    Method -指定计算阈值的方法

    -cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值

    -cv2.ADPTIVE_THRESH_GAUSSIAN_C:阈值取值相邻区域的加权和,权重为一个高斯窗口

  • Block Size 邻域大小(用来计算阈值的区域大小)
  • C 一个常数,阈值就等于区域亮度平均值或加权平均值减去这个常数

具体例程如下:

# -*- coding:utf-8 -*-

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('2.jpg',0)
img = cv2.medianBlur(img,5)#中值滤波制造明暗差距

ret,th1 =
cv2.threshold(img,127,255,cv2.THRESH_BINARY)
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]

#pyplot的绘图方法
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()

# -*- coding:utf-8 -*-

import numpy as np
import  cv2
from matplotlib import pyplot as plt

img = cv2.imread('2.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]

#pyplot的绘图方法
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()

书上的例图:

3. Otsu's 二值化

  这里要用到第一部分提到的retVal。

  在使用全局阈值时,我们就是随便给了一个数来做阈值,那我们怎么知道我们选取这个数是好是坏?答案就是不停尝试。如果是一幅双峰图像(即图像直方图中存在两个峰)呢?我们岂不是应该在两个峰之间的风骨选一个值作为阈值?这就是Otsu二值化需要做的。简单来说就是对一副双峰图像自动根据其直方图计算出一个阈值(对于非双峰图就没那么理想了)

  还是使用cv2.threshold(),但是需要多传入一个参数(flag):cv2.THRESH_OTSU。这时要把阈值设为0,然后算法会找到最优阈值,这个最优阈值就是retVal。如果不使用Otsu二值化,返回的retVal值与设定的阈值相等。

  例程中,输入图像是一幅带有噪声的图像,第一周方法,设127为全局阈值。第二种方法,直接使用Otsu二值化。第三种方法,我们首先使用一个5*5的高斯核去噪声,在使用Otsu二值化。

# -*- coding:utf-8 -*-

import numpy as np
import cv2
from matplotlib import pyplot as plt img = cv2.imread('6.jpg',0)
#全局阈值方法
ret1,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
#Otsu's 阈值方法,阈值一定要设定为0
ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
#高斯核滤波后的Otsu‘s阈值,(5,5)的高斯核,0为标准差(暂时不知道啥意思)
blur = cv2.GaussianBlur(img,(5,5),0)
ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.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 range(3):
plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
# 注意这里画直方图的方法,它的参数是一维数组,所以使用了(numpy)ravel方法,将多维数组化为一维数组
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()

结果如下:

教程中的例子更为明显:

OpenCV学习笔记(7)——图像阈值的更多相关文章

  1. [OpenCV学习笔记3][图像的加载+修改+显示+保存]

    正式进入OpenCV学习了,前面开始的都是一些环境搭建和准备工作,对一些数据结构的认识主要是Mat类的认识: [1.学习目标] 图像的加载:imread() 图像的修改:cvtColor() 图像的显 ...

  2. opencv学习笔记3——图像缩放,翻转和阈值分割

    #图像的缩放操作 #cv.resize(src,dsize,dst=None,,fx=None,fy=None,interpolation=None) #src->原图像,dsize->目 ...

  3. OpenCV学习笔记(10)——图像梯度

    学习图像梯度,图像边界等 梯度简单来说就是求导. OpenCV提供了三种不同的梯度滤波器,或者说高通滤波器:Sobel,Scharr和Lapacian.Sobel,Scharr其实就是求一阶或二阶导. ...

  4. opencv学习笔记(六)---图像梯度

    图像梯度的算法有很多方法:sabel算子,scharr算子,laplacian算子,sanny边缘检测(下个随笔)... 这些算子的原理可参考:https://blog.csdn.net/poem_q ...

  5. opencv学习笔记(七)---图像金字塔

    图像金字塔指的是同一图像不同分辨率的子图的集合,有向下取样金字塔,向上取样金字塔,拉普拉斯金字塔....它是图像多尺度表达的一种,最主要的是用于图像的分割 向下取样金字塔指高分辨率图像向低分辨率图像的 ...

  6. opencv学习笔记(五)----图像的形态学操作

    图像的形态学操作有基本的腐蚀和膨胀操作和其余扩展形态学变换操作(高级操作)-----开运算,闭运算,礼帽(顶帽)操作,黑帽操作...(主要也是为了去噪声,改善图像) 形态学操作都是用于处理二值图像(其 ...

  7. OpenCV学习笔记(3)——图像的基本操作

    获取图像的像素值并修改 获取图像的属性(信息) 图像的ROI() 图像通道的拆分及合并 1.获取并修改像素值 先读入图像装入一个图像实体,然后该实体相当于一个多维list,可以直接用数组操作提取像素信 ...

  8. OpenCV 学习笔记 02 使用opencv处理图像

    1 不同色彩空间的转换 opencv 中有数百种关于不同色彩空间的转换方法,但常用的有三种色彩空间:灰度.BRG.HSV(Hue-Saturation-Value) 灰度 - 灰度色彩空间是通过去除彩 ...

  9. (转) OpenCV学习笔记大集锦 与 图像视觉博客资源2之MIT斯坦福CMU

          首页 视界智尚 算法技术 每日技术 来打我呀 注册     OpenCV学习笔记大集锦 整理了我所了解的有关OpenCV的学习笔记.原理分析.使用例程等相关的博文.排序不分先后,随机整理的 ...

随机推荐

  1. Spingboot使用log4j2

    1.pom.xml加入log4j2,并同时把spring boot默认的logging去掉,注意一定要全部排除否则会报错. <dependency> <groupId>org. ...

  2. 6.redis

    1.Redis的安装以及客户端连接 安装:apt-get install redis-server 卸载:apt-get purge --auto-remove redis-server 启动:red ...

  3. Mac下的LDAP客户端 ApacheDirectoryStudio

    mac下的ldap browser,最开始下载的最新版本的 地址 http://directory.apache.org/studio/downloads.html 使用的时候经常卡死,尝试下载老版本 ...

  4. Liunx 用户权限之目录

    总结一下: 今天又对liunx权限的认知多了一点,就是关于目录的权限的作用 可以打个比方来形容就是:相当于一个大门 只有目录权限都有的情况下,才能够对目录中的文件进行目录权限操作 例如:drwxrwx ...

  5. Automatches

    import os def combine(ArrayList,count): ArrayList=list(ArrayList) newArrayList=[] for i in range(0,A ...

  6. 关于nmap扫描端口

    nmap查看一个服务器的端口,是通过扫描来实现的.所以在本机执行nmap扫描的端口有可能被防火墙阻止,在外部是访问不了的. 如:开启ORACLE监听后,在本机使用nmap 127.0.0.1是可以扫描 ...

  7. 数组遍历 forEach 方法

    数组的遍历 遍历数组,将数组中的所有元素都取出来. 使用for 循环执行数组的索引(length-1)相同的次数. var arr=["1", "5", &qu ...

  8. DOM添加

    ㈠添加元素的步骤 ⑴创建空元素 ⑵设置关键属性 ⑶将元素添加到DOM树   ㈡创建空元素 var elem = document.createElement('table');   示例: var t ...

  9. ELEMENT-UI 封装el-table 局部刷新row

    //关于封装的el-table行数据更新后如何局部更新row row.status=status; this.$set(this.$refs.elTable.$data.tableData,index ...

  10. HGOI20190810 省常中互测3

    Problem A  夏洛特 若当前处在点$(x,y)$下一时刻可以向该点四周任意方向走动一步, 初始在$(0,0)$是否存在一条合法的路线满足下列$n$个限制: 每一个限制形如$t_i , x_i ...