OpenCV中的图像阈值处理算法
Posted 卓晴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV中的图像阈值处理算法相关的知识,希望对你有一定的参考价值。
简 介: 本文讨论了如何通过图像阈值算法来对图像中特点对接进行隔离。 演示了几种不同的阈值分割(全局阈值分割)算法的结果。对于最简单的阈值算法,通过改变其中的阈值可以获得不同的分割效果。
关键词
: 阈值,图像分割,二值化
§00 前 言
由于需要使用到OpenCV中的阈值分割算法,所以下面将网页 Image Thresholding in OpenCV 中的一些内容汇总在这里,供以后大家参考。
仔细观察下面的动图,总共多少个数字你可以分辨出来。大多数人可以看到六七个数字,但实际上它里面包含更多的数字。
▲ 图1 阈值分割后的图片
正像动图循环显示的结果那样,你可以看到原图经过阈值分割后的结果:
- 所有的数字都呈现纯白色(它们具有255亮度值)、
- 其中数字“5”你可以看到,这个数字物在原始图像中你几乎看不到,是因为它的亮度值仅仅有5。
实际上,上图中的所有数字的亮度值与数字值是相同的。所以“255”是最亮的数字,“5”是最暗的数字。你记得在普通的灰度图中,每个像素的亮度值是从0 到 255。
因此,在阈值分割后的图片上识别数字比起原始图像要容易的多。就连一些文字识别的软件在处理阈值分割后的图像时也比起原始图像容易。阈值分割图像在机器视觉中有很多的应用,也是一些算法处理流水线中前级预处理的步骤。在阈值分割算法中有一些不同的变形。下面主要讨论“全局”阈值算法。
§01 全局阈值
那么什么叫做全局阈值图像处理呢?那就是对于图像中的所有像素都使用统一的阈值进行比较,在处理过程中阈值保持固定,这就叫做全局阈值处理。
全局阈值算法有两个输入:原始图像(src)以及阈值(thresh;产生一个输出(dst)图像。通过对比图像中(x,y)处的像素亮度 s r c ( x , y ) src\\left( x,y \\right) src(x,y) 以及阈值 threshold,根据比较的值赋予输出图像 d s t ( x , y ) dst\\left( x,y \\right) dst(x,y) 像素取值。比如当原始图像像素亮度大于阈值赋予输出图像亮度值为255,否则赋予为0。
最简单的一种全局阈值图像算法为固定阈值二值图像。
- 具体算法中,除了输入图像 src 以及阈值 thresh 之外,还有一个参数成为输出的最大值 maxValue;
- 对于每个位置(x,y)处的像素亮度值与固定阈值 thresh jnx;比较;
如果 s r c ( x , y ) ≥ t h r e s h src\\left( x,y \\right) \\ge thresh src(x,y)≥thresh ,那么输出 d s t ( x , y ) = max V a l u e dst\\left( x,y \\right) = \\max Value dst(x,y)=maxValue ;否则 d s t ( x , y ) = 0 dst\\left( x,y \\right) = 0 dst(x,y)=0 。
# Simple threshold function pseudo code
if src(x,y) > thresh
dst(x,y) = maxValue
else
dst(x,y) = 0
随着不同的阈值作用在 s r c ( x , y ) src\\left( x,y \\right) src(x,y) 上,所得到的输出图像 d s t ( x , y ) dst\\left( x,y \\right) dst(x,y) 结果也不一样。下面让我们查看不同的全局阈值分割的结果。
# import opencv
import cv2
# Read image
src = cv2.imread("threshold.png", cv2.IMREAD_GRAYSCALE);
# Basic threhold example
th, dst = cv2.threshold(src, 0, 255, cv2.THRESH_BINARY);
cv2.imwrite("opencv-threshold-example.jpg", dst);
# Thresholding with maxValue set to 128
th, dst = cv2.threshold(src, 0, 128, cv2.THRESH_BINARY);
cv2.imwrite("opencv-thresh-binary-maxval.jpg", dst);
# Thresholding with threshold value set 127
th, dst = cv2.threshold(src,127,255, cv2.THRESH_BINARY);
cv2.imwrite("opencv-thresh-binary.jpg", dst);
# Thresholding using THRESH_BINARY_INV
th, dst = cv2.threshold(src,127,255, cv2.THRESH_BINARY_INV);
cv2.imwrite("opencv-thresh-binary-inv.jpg", dst);
# Thresholding using THRESH_TRUNC
th, dst = cv2.threshold(src,127,255, cv2.THRESH_TRUNC);
cv2.imwrite("opencv-thresh-trunc.jpg", dst);
# Thresholding using THRESH_TOZERO
th, dst = cv2.threshold(src,127,255, cv2.THRESH_TOZERO);
cv2.imwrite("opencv-thresh-tozero.jpg", dst);
# Thresholding using THRESH_TOZERO_INV
th, dst = cv2.threshold(src,127,255, cv2.THRESH_TOZERO_INV);
cv2.imwrite("opencv-thresh-to-zero-inv.jpg", dst);
§02 分割举例
2.1 输入图像
下面就是用于举例中的输入图像,其中具有多个数字,数字的亮度值与数字本身取值相同。比如“200”的亮度值就是200, “64”的亮度值就是64,其余以此类推。
▲ 图2.1.1 用于举例的输入图像
2.2 几种不同阈值算法处理结果
2.2.1 图像二值化
这是最常用的阈值图像分割算法。具体的处理过程为:
# Binary Threshold
if src(x,y) > thresh
dst(x,y) = maxValue
else
dst(x,y) = 0
(1)Python演示程序
# import opencv
import cv2
# Read image
src = cv2.imread("threshold.png", cv2.IMREAD_GRAYSCALE)
# Set threshold and maxValue
thresh = 0
maxValue = 255
# Basic threshold example
th, dst = cv2.threshold(src, thresh, maxValue, cv2.THRESH_BINARY);
(2)处理结果
下图显示了处理结果。其中:
-
算法参数:
-
thresh
:0
maxValue
:255
▲ 图2.2.1 二值化处理结果(thresh=0, maxValue=255)
如果 thresh=127,那么所有数字小于127的都将会消除。
▲ 图2.2.2 二值化分割结果(thresh=127, maxValue=255)
改变 maxValue=128。下面是处理结果:
▲ 图2.2.3 二值化处理结果(Thresh=0, maxValue=128)
2.2.2 反向二值化
反向二值化就是在输出的二值图像中按照阈值比较结果取反:
- 当原始图像亮度大于阈值时,输出图像亮度为0
- 反之,输出图像亮度取 maxValue
Python语言调用格式:
th, dst = cv2.threshold(src, thresh, maxValue, cv2.THRESH_BINARY_INV)
下面给出了反向二值化输出结果。实际上是前面正常二值化取反。
▲ 图2.2.4 反向二值化结果(thresh=127, maxValue=0)
2.2.3 截断阈值分割
这种阈值分割方法:
- 当原始图像亮度值比阈值高的时候,输出图像的亮度设置为阈值;
- 否则输出图像的亮度取原始图像的像素亮度;
- maxValue值在此算法中没有用;
# Truncate Threshold
if src(x,y) > thresh
dst(x,y) = thresh
else
dst(x,y) = src(x,y)
Python语言调用格式:
th, dst = cv2.threshold(src, thresh, maxValue, cv2.THRESH_TRUNC)
下面显示了截断阈值分割的处理结果。
-
算法参数:
-
thresh
:127
maxValue
:忽略
▲ 图2.2.5 截断阈值分割结果(thresh=127)
2.2.4 逆向截取阈值分割
这种截取阈值分割的算法是对所有小于阈值的像素都置为0,否则保持原来的像素亮度值。
# Threshold to Zero
if src(x,y) > thresh
dst(x,y) = src(x,y)
else
dst(x,y) = 0
▲ 图2.2.6 逆向截取阈值图像分割算法结果(thresh=127)
2.2.5 反转逆向阈值分割
在这种算法中,
- 对于所有亮度值大于阈值的像素对应输出图像中都设置为0;
- 否则,去原来像素值;
- maxValue 忽略;
# Inverted Threshold to Zero
if src(x,y) > thresh
dst(x,y) = 0
else
dst(x,y) = src(x,y)
Python语言调通格式:
th, dst = cv2.threshold(src, thresh, maxValue, cv2.THRESH_TOZERO_INV)
下面是反转逆向阈值分割结果,可以看到在一些数字边缘出现一些特殊的便捷效果。这些数字的边缘从0 过渡到正常待渎职,有少量的像素落在阈值之外,所以出现了中特殊的边缘提取到的结果。
▲ 图2.2.7 反转逆向阈值分割结果(thresh=127)
以上是关于OpenCV中的图像阈值处理算法的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV-Python实战——OpenCV用于图像分割的阈值技术(含大量示例,建议收藏)
OpenCV-Python实战——OpenCV用于图像分割的阈值技术(含大量示例,建议收藏)