• 简单阈值,自适应阈值,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. 多线程编程-- part 9 信号量:Semaphore

    Semaphore简介 Semaphore是一个计数信号量,它的本质是一个"共享锁". 信号量维护了一个信号量许可集.线程可以通过调用acquire()来获取信号量的许可:当信号量 ...

  2. python、第一篇:初识数据库

    一 数据库管理软件的由来 基于我们之前所学,数据要想永久保存,都是保存于文件中,毫无疑问,一个文件仅仅只能存在于某一台机器上. 如果我们暂且忽略直接基于文件来存取数据的效率问题,并且假设程序所有的组件 ...

  3. DP问题练习2:网格路径数量计算问题

    DP问题练习2:网格路径数量计算问题 问题描述 有一个机器人的位于一个 m × n 个网格左上角. 机器人每一时刻只能向下或者向右移动一步.机器人试图达到网格的右下角. 问有多少条不同的路径? 样例: ...

  4. server version for the right syntax to use near 'USING BTREE 数据库文件版本不合导致的错误

    MySQL 返回:#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MyS ...

  5. ES数据架构与关系数据库Mysql

    ES数据架构的主要概念(与关系数据库Mysql对比) MySQL ElasticSearch Database Index Table Type Row Document Column Field S ...

  6. 阿里云-docker安装mysql

    1.检查内核版本,必须是3.10及以上 uname ‐r 2.安装docker yum install docker 3.输入y确认安装 4.启动docker:service docker start ...

  7. 基于初始种子自动选取的区域生长(python+opencv)

    算法中,初始种子可自动选择(通过不同的划分可以得到不同的种子,可按照自己需要改进算法),图分别为原图(自己画了两笔为了分割成不同区域).灰度图直方图.初始种子图.区域生长结果图.另外,不管时初始种子选 ...

  8. 完整的IT项目开发流程

    一般情况下,企业开发软件时会按照基线和定制两块并行方式执行项目开发工作.无论什么公司,都需要遵从一套成熟的产品研发过程体系,才能做出质量较好的产品.因此,如果出现项目较多的情况,应该合理地安排基线和定 ...

  9. DevExpress ASP.NET Bootstrap v19.1版本亮点:Editors控件

    行业领先的.NET界面控件DevExpress 正式发布了v19.1版本,本文将以系列文章的方式为大家介绍DevExpress ASP.NET Bootstrap Controls中Editors.G ...

  10. PHP循环while do while循环

    <?php #从1打印到10,除了5 $i=1; while ($i<10) { if ($i==5) { $i++; continue; } echo $i++."<br ...