• 简单阈值,自适应阈值,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. openCV3 Python编译指南

    这里主要对openCV官网的<Installation in Linux>文档进行了翻译和解释 原文见:https://docs.opencv.org/3.4.1/doc/tutorial ...

  2. k-means 非监督学习聚类算法

    非监督学习 非监督学习没有历史样本数据和标签,直接对数据分析或得结果. k-means 使用 >>> from sklearn.cluster import KMeans >& ...

  3. AES加密解密 Java中运用

    AES全称 Advanced Encryption Standard, 高级加密算法,更加安全,可取代DES. Aes: package com.blog.d201706.encrypt; impor ...

  4. svn 权限设置

    /***********************************************************/ //SVNSubversion 用户权限管理 //资料来源:网络.总结 // ...

  5. 第二章 Vue快速入门-- 27 字符串的padStart方法使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  6. 【HDU5890】Eighty seven

    题目大意:给定 N 个数,M 个询问,每次询问如果去掉三个数(可能相同),能否选择恰好 10 个数字,凑出 87 这个数. 题解:骚操作.. 集合凑数问题是一个很经典的模型,即:背包问题. 先进行预处 ...

  7. Spring MVC 设置UTF-8编码

    按照需求选其中之一即可吧. 修改读取参数时候的编码: 在web.xml中: 添加一个过滤器(filter),注册 org.springframework.web.filter.CharacterEnc ...

  8. grunt-css-sprite css 代码中的切片合并

    安装插件:npm install grunt-css-sprite --save-dev grunt-css-sprite主要功能:1.对 css 文件进行处理,收集切片序列,生成雪碧图2.在原css ...

  9. 【BZOJ 3682】Phorni

    题目链接 题目描述 Phorni 是一个音之妖精,喜欢在你的打字机上跳舞. 一天,阳光映射到刚刚淋浴过小雨的城市上时,Phorni 用魔法分裂出了许多个幻影,从 1 到 n 编号. 她的每一个幻影都站 ...

  10. VAssistX 常用快捷键

    函数跳转 Alt + G - 函数定义和声明的跳转Alt + O - 在.h与.cpp文件中实现相互转换Alt + M - 列出当前文件所有的函数Ctrl + Tab - 切换标签 查找 Ctrl + ...