• 简单阈值,自适应阈值,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. python视频学习笔记5(高级变量的类型)

    知识点回顾: Python 中数据类型可以分为 **数字型** 和 **非数字型*** 数字型 * 整型 (`int`) * 浮点型(`float`) * 布尔型(`bool`) * 真 `True` ...

  2. java笔记web

    1,spring请求同,返回同一个界面 Dubbo消费者无法连接到生产者提供的服务?内网IP? https://blog.csdn.net/xlgen157387/article/details/52 ...

  3. linux命令详解——umask

    当我们登录系统之后创建一个文件总是有一个默认权限的,那么这个权限是怎么来的呢?这就是umask干的事情.umask设置了用户创建文件的默认 权限,它与chmod的效果刚好相反,umask设置的是权限& ...

  4. 使用go语言开发一个后端gin框架的web项目

    用liteide来开发go的后端项目,需要注意的是环境变量要配置正确了 主要是GOROOT, GOPATH, GOBIN, PATH这几个, GOPATH主要用来存放要安的包,主要使用go get 来 ...

  5. Summer training round2 #7 (Training #23)

    A:约瑟夫环 套公式 B:线性筛素数 C:投骰子 概率DP F:有权无向图的生成树(边最大值和最小值只差最小) 直接kruskal G:状压BFS或者双向BFS H:模拟题 I:几何题 J:高斯消元

  6. git中working tree, index, commit

    这三个名字可以简单理解为文件在本地仓库存在的三种不同的位置. 如下,是做commit提交两段提交过程,工作区(working tree),暂存区(index)和 branch(commit). wor ...

  7. Prometheus+Granfana

    二.虚机(服务器)方式prometheus在虚机(服务器)中安装运行. 命令行启动在安装完成以后,可以直接在命令行启动.启动方式通常是: ./prometheus --config.file=prom ...

  8. VCL界面开发必备装备!DevExpress VCL v19.1.5你值得拥有

    DevExpress VCL Controls是 Devexpress公司旗下最老牌的用户界面套包.所包含的控件有:数据录入,图表,数据分析,导航,布局,网格,日程管理,样式,打印和工作流等,让您快速 ...

  9. std::this_thread::sleep_until

    头文件:<thread>                  (C++11) template<class Clock, class Duration> void sleep_u ...

  10. Python 文件I/OⅡ

    File对象的属性 一个文件被打开后,你有一个file对象,你可以得到有关该文件的各种信息. 以下是和file对象相关的所有属性的列表: 如下实例: 以上实例输出结果: close()方法 File ...