• 简单阈值,自适应阈值,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. java中的compareto方法的详细介绍

    java中的compareto方法的详细介绍 Java Comparator接口实例讲解(抽象方法.常用静态/默认方法) 一.java中的compareto方法 1.返回参与比较的前后两个字符串的as ...

  2. 工具安装——linux下安装JDK1.8

    1.查看Linux环境自带JDK 使用命令:# rpm -qa|grep gcj 显示内容其中包含相应信息# java-x.x.x-gcj-compat-x.x.x.x-xxjpp# java-x.x ...

  3. Vue自行封装常用组件-弹出框

    使用方法: 1.在父组件中引入"box.vue" //import popUpBox from "./box.vue";   2.在父组件中注册 popUpBo ...

  4. eclipse查看jsp出现failed to create the part's controls的解决方法

    问题描述 最近eclipse出现了一下问题,某个类无法打开,显示Failed to create the part’s controls ,如图: 问题解决 安装的JDK 版本估计有冲突导致IDE出现 ...

  5. 好用的数据库压缩软件wingzip

    有时候我们导出.sql格式的数据库备份文件过大,超过了某些虚拟空间数据库支持的文件大小限制,我们没办法修改phpMyAdmin 导入MySQL数据库文件大小限制 只能通过压缩数据库来达到上传数据库的目 ...

  6. 【hdu 6071】Lazy Running

    菜鸡永远都在做着变聚的梦. 题意 有 \(4\) 个点连成一个环,连接顺序依次为 \(1-2-3-4-1\).相邻两个点之间有个距离 \(d_{i,i+1}\)(特别地,当 \(i=4\) 时为 \( ...

  7. 写一个基于TCP协议套接字,服务端实现接收客户端的连接并发

    ''' 写一个基于TCP协议套接字,服务端实现接收客户端的连接并发 ''' client import socket import time client = socket.socket() clie ...

  8. 2018年最佳JavaScript数据可视化和图表库

    现在有很多图表库,但哪一个最好用?这可能取决于许多因素,如业务需求,数据类型,图表本身的目的等等.在本文中,每个JavaScript图表库将与一些关键因素进行比较,包括图表类型,商业或免费和开源状态. ...

  9. Acwing-96-奇怪的汉诺塔(递推)

    链接: https://www.acwing.com/problem/content/description/98/ 题意: 汉诺塔问题,条件如下: 1.这里有A.B.C和D四座塔. 2.这里有n个圆 ...

  10. LightOJ-1027-A Dangerous Maze(概率)

    链接: https://vjudge.net/problem/LightOJ-1027#author=634579757 题意: You are in a maze; seeing n doors i ...