Python-OpenCV(7)

接着上篇,这次主要讲一个主题就是:

图像的阈值处理

主要涵盖的内容点包括:

简单阈值 自适应阈值 Otsu’s 二值化

大家可能不是很清楚阈值处理的用途在什么地方,我举几个例子:

图像的二值化

区域的分割

图像的点/线/边缘检测

所以用途还是很广的,实则这块属于图像的分割范畴

ps: 有兴趣的可以看看数字图像处理的MATLAB实现这本书,讲的还是很不错的,代码使用MATLAB编写,推荐阅读

基础知识

对图像做阈值处理,基本的想法就是将图像分成前景和背景,通过选择一个阈值T,使得前景和背景分离,经过阈值处理之后的图像g(x,y)被定义为:

g(x,y)= a if f(x,y) > T g(x,y)= b if f(x,y) <= T

标注为a的像素对应目标,标注为b的像素对应背景,假设此时我们令a=1b=0,那么此时图像就只有两个值0,1了,图像显示出来就是只有黑(0)白(1) ,亦即二值化

简单阈值

这种方法非常简单,一但像素值高于阈值时,我们给这个像素赋予一个新值(可能是白色),否则我们给它赋予另外一种颜色(也许是黑色)

cv2.threshhold(src, thresh, maxval, type[, dst])

参数:

cv2.THRESH_BINARY:img(x,y)>threshold ,dst(x,y) = max_value; 否则,dst(x,y)=0

cv2.THRESH_BINARY_INV:img(x,y)>threshold ,dst(x,y) = 0; 否则,dst(x,y)= max_value

cv2.THRESH_TRUNC:img(x,y)>threshold,dst(x,y) = max_value; 否则dst(x,y) = src(x,y)

cv2.THRESH_TOZERO:img(x,y)>threshold,dst(x,y) = src(x,y) ; 否则 dst(x,y) = 0

cv2.THRESH_TOZERO_INV:img(x,y)>threshold,dst(x,y) = 0 ; 否则 dst(x,y) = src(x,y)

给个图帮助大家理解:

从上到下,分别对应上面的五个参数

代码:

__author__ = 'gavinzhou'
# -*- coding: utf-8 -*-

import cv2
import numpy as np
from matplotlib import pyplot as plt

# read the original images
img = cv2.imread("./images/1.png")
# convert to gray image
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# convert to binary image
ret, binary_img = cv2.threshold(gray_img, 100, 255, cv2.THRESH_BINARY)

cv2.imshow("ori", img)
cv2.imshow("binary1", binary_img)
cv2.waitKey(10000)
cv2.destroyAllWindows()

结果:

自适应阈值

上面的阈值选择很简单,但是存在很大的问题:

我们使用是全局阈值,整幅图像采用同一个数作为阈值。这种方法并不适应于所有情况,尤其是当同一幅图像上的不同部分的具有不同亮度时

假如我们将上面的阈值从100调整到200,大家看看效果:

几乎什么都看不见了,是不是?所以咱们还需要个更加智能点的方法,我们希望这个方法可以:

  1. 采用自适应阈值
  2. 阈值是根据图像上的每一个小区域计算与其对应的阈值得到的

因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果,这个方法就是自适应阈值

cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])

参数:

cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值

cv2.ADPTIVE_THRESH_GAUSSIAN_C:阈值取值相邻区域的加权和,权重为一个高斯窗口

Block Size:邻域大小(用来计算阈值的区域大小)

C:阈值等于的平均值或者加权平均值减去这个常数

注意:

block_size参数决定局部阈值的block的大小,block很小时,如block_size=3 or 5 or 7时,表现为边缘提取函数。当把block_size设为比较大的值时,如block_size=21、51等,便是二值化 代码:

__author__ = 'gavinzhou'
# -*- coding: utf-8 -*-

import cv2
from matplotlib import pyplot as plt

# read the original images
img = cv2.imread("./images/1.png")

# convert to gray image
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# convert to binary image
binary_img1 = cv2.adaptiveThreshold(gray_img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
binary_img2 = cv2.adaptiveThreshold(gray_img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 37, 2)
binary_img3 = cv2.adaptiveThreshold(gray_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
binary_img4 = cv2.adaptiveThreshold(gray_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 37, 2)

cv2.imshow("binary1", binary_img1)
cv2.imshow("binary2", binary_img2)
cv2.imshow("binary3", binary_img3)
cv2.imshow("binary4", binary_img4)
cv2.waitKey(10000)
cv2.destroyAllWindows()

结果:

Otsu’s Method

其实大家已经看到,上面的方法不好,对于全局阈值我们需要不停的去试,但是加入我们图像很多的话,我们就没法做了,因为我们不可能对每个图像都去试; 对于自适应阈值,其和局部的关系很大,参数也是要调节的,调节的不好,效果也很不行;

解决方法就是otsu's方法,数学原理很复杂,大家想知道的化,自己去搜下相关资料来看看,或者看看我上面推荐的那本数字图像处理的MATLAB实现,讲的很清楚,这里我们侧重实战,原理就不讲了哈!

cv2.threshold(src, 0, maxval, cv2.THRESH_OTSU+type[, dst])

就是将阈值设置为0,flag出加上cv2.THRESH_OTSU即可

代码:

__author__ = 'gavinzhou'
# -*- coding: utf-8 -*-

import cv2
from matplotlib import pyplot as plt

# read the original images
img = cv2.imread("./images/1.png")
# convert to gray image
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# convert to binary image
ret2, binary_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)


cv2.imshow("ori", img)
cv2.imshow("binary", binary_img)
print "Otsu's value is:", ret2

cv2.waitKey(10000)
cv2.destroyAllWindows()

结果:

大家自己看吧,效果比上面的是不是好很多!

此时console打印的是:

Otsu’s value is: 88.0

otsu方法寻找到的阈值是88,自动寻找,省时省力,效果好

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一心无二用,本人只专注于基础图像算法的实现与优化。

图像偏色检测算法,速度快,效果好,共享给大家。      式中 ,M、 N分别为图像的宽和高,以像素为单位。在 a - b色度平面上,等效圆的中心坐标为 ( da , db ) ,半径为 M 。等效

     本文的算法并不是我自己提出的,而是一些论文中提出的,详见 :      1、基于图像分析的偏色检测及颜色校正方法 徐晓昭 , 蔡轶珩 , 刘长江 , ...

2518

用Python的长短期记忆神经网络进行时间序列预测

长短期记忆递归神经网络具有学习长的观察序列的潜力。

1.7K8
来自专栏深度学习自然语言处理

word2vec理论与实践

导读 本文简单的介绍了Google 于 2013 年开源推出的一个用于获取 word vector 的工具包(word2vec),并且简单的介绍了其中的两个训练...

2716
来自专栏AILearning

【Scikit-Learn 中文文档】聚类 - 无监督学习 - 用户指南 | ApacheCN

2.3. 聚类 未标记的数据的 Clustering(聚类) 可以使用模块 sklearn.cluster 来实现。 每个 clustering algo...

1.1K10
来自专栏Petrichor的专栏

深度学习: Faster R-CNN 网络

网络结构有两种,一种是将ZFNet(扔掉了尾端的全连接层)拿来用,另一种则是将VGG拿来用(扔掉了尾端的全连接层)。论文中给出的是第一种(绿框内为拿来用的那部分...

1574
来自专栏贾志刚-OpenCV学堂

OpenCV Gabor滤波器实现纹理提取与缺陷分析

Gabor滤波器是OpenCV中非常强大一种滤波器,广泛应用在纹理分割、对象检测、图像分维、文档分析、边缘检测、生物特征识别、图像编码与内容描述等方面。Gabo...

2045
来自专栏人人都是极客

OpenCV和SVM分类器在自动驾驶中的车辆检测

这次文章的车辆检测在车辆感知模块中是非常重要的功能,本节课我们的目标如下: 在标记的图像训练集上进行面向梯度的直方图(HOG)特征提取并训练分类器线性SVM分类...

5596
来自专栏人人都是极客

OpenCV和SVM分类器在自动驾驶中的车辆检测

这次文章的车辆检测在车辆感知模块中是非常重要的功能,本节课我们的目标如下:

68710
来自专栏用户2442861的专栏

openCV—Python(10)—— 图像阈值化处理

992
来自专栏糊一笑

那些年下过的大雨

想了解一下用纯CSS和JS怎么实现一段下雨的动画,于是去CodePen上面搜了一下,发现了很多很有意思的东西。有空可以常去上面逛逛,在对技术产生敬畏的同时也能学...

2855

扫码关注云+社区