opencv入门11:图像阀值-thresholding

一个简单的阈值例子就是选择一个像素值p,然后将小于p的所有像素强度设置为零,并且将所有像素值大于p设置为255.以这种方式,我们能够创建图像的二进制表示。

一、阈值化的类型:

OpenCV中提供了阈值(threshold)函数: threshold 。这个函数有5种阈值化类型:

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

为了解释阈值分割的过程,我们来看一个简单有关像素灰度的图片,该图如下。该图中的蓝色水平线代表着具体的一个阈值。


图·1

阈值类型1:二进制阈值化 cv2.THRESH_BINARY

  • 该阈值化类型如下式所示:
  • 解释:在运用该阈值类型的时候,先要选定一个特定的阈值量,比如:125,这样,新的阈值产生规则可以解释为大于125的像素点的灰度值设定为最大值(如8位灰度值最大为255),灰度值小于125的像素点的灰度值设定为0。
    图·2

阈值类型2:反二进制阈值化 cv2.THRESH_BINARY_INV

  • 该阈值化类型如下式所示:
  • 解释:该阈值化与二进制阈值化相似,先选定一个特定的灰度值作为阈值,不过最后的设定值相反。(在8位灰度图中,例如大于阈值的设定为0,而小于该阈值的设定为255)。
    图·3

阈值类型3:截断阈值化 cv2.THRESH_TRUNC

  • 该阈值化类型如下式所示:
  • 解释:同样首先需要选定一个阈值,图像中大于该阈值的像素点被设定为该阈值,小于该阈值的保持不变。(例如:阈值选取为125,那小于125的阈值不改变,大于125的灰度值(230)的像素点就设定为该阈值)。
    图·4

阈值类型4:阈值化为0 cv2.THRESH_TOZERO

  • 该阈值化类型如下式所示:
  • 解释:先选定一个阈值,然后对图像做如下处理:1 像素点的灰度值大于该阈值的不进行任何改变;2 像素点的灰度值小于该阈值的,其灰度值全部变为0。
    图·5

阈值类型5:反阈值化为0 cv2.THRESH_TOZERO_INV

  • 该阈值化类型如下式所示:
  • 解释:原理类似于0阈值,但是在对图像做处理的时候相反,即:像素点的灰度值小于该阈值的不进行任何改变,而大于该阈值的部分,其灰度值全部变为0。
    图·6

二、simple thresholding 简单的阈值方法:

应用简单的阈值方法需要人为干预。
我们必须指定一个阈值T.低于T的所有像素强度都被设置为0.而所有大于T的像素强度被设置为255。

cv2.threshold( src_gray, dst, threshold_value, max_BINARY_value,threshold_type )

  • src_gray: 输入的灰度图像的地址。
  • dst: 输出图像的地址。
  • threshold_value: 进行阈值操作时阈值的大小。
  • max_BINARY_value: 设定的最大灰度值(该参数运用在二进制与反二进制阈值操作中)。
  • threshold_type: 阈值的类型。从上面提到的5种中选择出的结果。
    图·7
图·8

三、adaptive thresholding 自适应阀值

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

cv2.adaptiveThreshold(image,max_BINARY_value,Adaptive_Method,threshold_type,Block_Size,C)

  • max_BINARY_value: 设定的最大灰度值(该参数运用在二进制与反二进制阈值操作中)。
  • threshold_type: 阈值的类型。从上面提到的5种中选择出的结果。

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

  • Adaptive Method- 指定计算阈值的方法。
    • cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平
      均值
    • cv2.ADPTIVE_THRESH_GAUSSIAN_C:阈值取值相邻区域
      的加权和,权重为一个高斯窗口。
  • Block Size - 邻域大小(用来计算阈值的区域大小)。表明我们要检查图像的11×11像素区域,而不是像在简单的阈值方法中那样尝试对图像进行全局阈值
  • C - 这就是是一个常数,阈值就等于的平均值或者加权平均值减去这个常数。我们提供一个简单的叫做C的参数。这个值是一个从平均值中减去的整数,使我们可以微调我们的阈值

一般来说,在平均自适应阈值和高斯自适应阈值之间进行选择需要在您的最后进行一些实验。要改变的最重要的参数是邻域大小和C,即从平均值中减去的值。通过试验这个值,你将能够显着地改变你的阈值的结果。

import numpy as np 
import argparse
import cv2

ap = argparse.ArgumentParser()
ap.add_argument("-i","--image",required =True, help="Path to the image")
args = vars(ap.parse_args())

image = cv2.imread(args["image"])
image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
blured = cv2.GaussianBlur(image,(5,5),0)
cv2.imshow("Image",image)

thresh =cv2.adaptiveThreshold(blured, 255 ,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV,11,4)
cv2.imshow("mean thresh",thresh)

thresh =cv2.adaptiveThreshold(blured, 255 ,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,15,3)
cv2.imshow("GAUSSIAN thresh",thresh)
cv2.waitKey(0) 

图·9

四、Otsu’s 二值化 和 Riddler-Calvard

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

mahotas.thresholding.otsu() 和 mahotas.thresholding.rc()

from __future__ import print_function
import numpy as np 
import argparse
import mahotas
import cv2

ap = argparse.ArgumentParser()
ap.add_argument("-i","--image",required =True, help="Path to the image")
args = vars(ap.parse_args())

image = cv2.imread(args["image"])
image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(image,(5,5),0)
cv2.imshow("Image",image)

T = mahotas.thresholding.otsu(blurred)
#为了计算T的最优值,我们使用mahotas.thresholding包中的otsu函数
print("Otsu`s threshold:{}".format(T))
thresh = image.copy()
thresh[thresh>T] = 255
thresh[thresh<T] = 0
thresh = cv2.bitwise_not(thresh)
# 首先,我们制作灰度图像的副本,以便使图像达到阈值。
# 第20行然后使任何值大于T white,
# 而第21行将所有剩余的不是白色的像素变成黑色像素。
# 然后我们通过使用cv2.bitwise_not来反转我们的阈值。
# 这相当于在本章前面的例子中应用cv2.THRESH_BINARY_INV阈值类型。
cv2.imshow("Ostu",thresh)

T = mahotas.thresholding.rc(blurred)
# 另一种方法找到最优值T 时要牢记Riddler-Calvard方法。
# 使用mahotas.thresholding中的rc函数
print("Riddler-Calvard:{}".format(T))
thresh = image.copy()
thresh[thresh>T] = 255
thresh[thresh<255] = 0
thresh = cv2.bitwise_not(thresh)
cv2.imshow("Riddler-Calvard",thresh)
cv2.waitKey(0)

图·10

努力常态化。
更多文章请关注我的博客:https://harveyyeung.github.io

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容