图像处理阈值

2018-12-02 10:55:25 shanwenkang 阅读数 3276

阈值

我们将图像分块最简单的方法就是设定一个阈值对图像进行二值化处理,那么这个阈值我们应该如何选择呢

对于图像的直方图存在明显边界的图像,我们可以很容易找到这个阈值,但是如果图像直方图分界不明显,那么这个阈值的寻找将变得十分困难。因此我们存在全局阈值与局部阈值两种

全局阈值

全局阈值就是在整幅图像中我们只有一个阈值来对图像进行二值化,但是其存在其局限性,例如图像中存在高斯噪声的情况下,我们无法找到一个很好的阈值将图像的边界分开

另外如果图像的边界是在局部对比下出现的,即不同位置阈值不同,那么全局阈值的效果也非常不好

我们先不管全局阈值的缺点,我们来看看我们如何通过计算来获得这个全局阈值T呢?我们又OTSU'S算法

下面是一些数学概念在图像上的体现

OTSU算法就是想把图像分为两个块,然后使得这两个块之间的方差最大,也就是最大化两个块的均值与全局均值的差的平方

由于只存在这么一个阈值,那么我们在计算的时候可以简单地让这个值遍历0-255,然后找到σB最大的值,这个值就是我们要的阈值。我们可以理解为这个值把图像分为了相距最远的两块。我们在matlab中有graythresh这个函数来实现这个过程

下图就显示了一个OTSU算法不是很理想的例子

为了克服以上缺点我们有两点解决方法:1.先通过低通滤波器去噪再用OTSU 2.只在考虑边缘部分的像素来计算阈值,这样可以大大减少其他不重要部分对阈值计算过程的影响

局部阈值

下面让我们来看看局部阈值/自适应阈值。它的原理就是将图像分块,对于不同的部分应用不同的阈值,在matlab中我们有blockproc这个函数来实现这个过程

我们看到相比于之前,效果确实有很大的提升,但是缺点也特别明显,就是图像会出现分块化

我们可以调小块的大小,但是这样的话会出现如果块内像素值变化不大的话,块内像素被全部分作黑或白而缺失了边界(例如右上角窗户的上方黑色的窗框内有白色的像素块)。因此块的选择是十分重要的

更好的方式是我们在每个像素周围的一个区域内来计算阈值,根据这个块内的均值方差来计算这个像素的值是1还是0

RGB图阈值

除了将阈值在灰度图上应用,我们还可以将其应用在RGB图中,我们可以设定一种颜色,来得到与这种颜色相近颜色的物体

例如我们取下图丝带的颜色可以得到如右图的结果

 

 

2018-12-23 13:18:06 lx_xin 阅读数 1980

基本概念

图像阈值分割是图像处理中最基本也是最常用的方法之一,主要用于将图像中的像素点划分为两个或者多个类别,从而得到便于处理的目标对象。

类别划分

按照阈值作用范围分:全局阈值分割,局部阈值分割;
按照阈值选取准则函数分:最大熵法,类间方差法,交叉熵法,最小误差法,模糊熵法;
按照阈值个数分:单阈值法和多阈值法;

2018-03-29 14:18:43 bjbz_cxy 阅读数 17250
的意思是界限,故阈值又叫临界值,是指一个效应能够产生的最低值或最高值。
在图像处理中它的意思是颜色转换的临界点,该方法只用于二值化的图像中
列如在自然中每一种颜色都有一个值,通常由RGB(即红、绿、蓝三原色)按比例混合就会得到各种不同的颜色。阈值处理图片是对颜色进行特殊处理的一种方法。
详细说,阈值是一个转换临界点,不管你的图片是什么样的彩色,它最终都会把图片当黑白图片处理,也就是说你设定了一个阈值之后,它会以此值作标准,凡是比该值大的颜色就会转换成白色,低于该值的颜色就转换成黑色,所以最后的结果是,你得到一张黑白的图片。

用阈值的作用:得到一张对比度不同的黑白图片

阈值可以是最小值:某一性能特征不能低于该值。
2018-07-04 21:37:59 qq_40962368 阅读数 16264

图像的阈值处理

      一幅图像包括目标物体、背景还有噪声,要想从多值的数字图像中直接提取出目标物体,常用的方法就是设定一个阈值T,用T将图像的数据分成两部分:大于T的像素群和小于T的像素群。这是研究灰度变换的最特殊的方法,称为图像的二值化(Binarization)。

       阈值分割法的特点是:适用于目标与背景灰度有较强对比的情况,重要的是背景或物体的灰度比较单一,而且总可以得到封闭且连通区域的边界。

(一)简单阈值

选取一个全局阈值,然后就把整幅图像分成非黑即白的二值图像。

函数为cv2.threshold( )

这个函数有四个参数,第一个是原图像矩阵,第二个是进行分类的阈值,第三个是高于(低于)阈值时赋予的新值,第四个是一个方法选择参数,常用的有:

  • cv2.THRESH_BINARY(黑白二值)
  • cv2.THRESH_BINARY_INV(黑白二值翻转)
  • cv2.THRESH_TRUNC(得到额图像为多像素值)
  • cv2.THRESH_TOZERO(当像素高于阈值时像素设置为自己提供的像素值,低于阈值时不作处理)
  • cv2.THRESH_TOZERO_INV(当像素低于阈值时设置为自己提供的像素值,高于阈值时不作处理)

这个函数返回两个值,第一个值为阈值,第二个就是阈值处理后的图像矩阵。

img = cv2.imread('4.jpg', 0)
ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)  # 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)  # 高于阈值时像素设置为255,低于阈值时不作处理
ret, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)  # 低于阈值时设置为255,高于阈值时不作处理

print(ret)

cv2.imshow('thresh1', thresh1)
cv2.imshow('thresh2', thresh2)
cv2.imshow('thresh3', thresh3)
cv2.imshow('thresh4', thresh4)
cv2.imshow('thresh5', thresh5)
cv2.imshow('grey-map', img)
cv2.waitKey(0)
cv2.destroyAllWindows()


(二)自适应阈值

一中的简单阈值是一种全局性的阈值,只需要设定一个阈值,整个图像都和这个阈值比较。而自适应阈值可以看成一种局部性的阈值,通过设定一个区域大小,比较这个点与区域大小里面像素点 的平均值(或者其他特征)的大小关系确定这个像素点的情况。使用的函数为:

# 第一个参数为原始图像矩阵,第二个参数为像素值上限,第三个是自适应方法(adaptive method):
#                                              -----cv2.ADAPTIVE_THRESH_MEAN_C:领域内均值
#                                              -----cv2.ADAPTIVE_THRESH_GAUSSIAN_C:领域内像素点加权和,权重为一个高斯窗口
# 第四个值的赋值方法:只有cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV
# 第五个Block size:设定领域大小(一个正方形的领域)
# 第六个参数C,阈值等于均值或者加权值减去这个常数(为0相当于阈值,就是求得领域内均值或者加权值)

# 这种方法理论上得到的效果更好,相当于在动态自适应的调整属于自己像素点的阈值,而不是整幅图都用一个阈值

img = cv2.imread('4.jpg', 0)
ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 第一个参数为原始图像矩阵,第二个参数为像素值上限,第三个是自适应方法(adaptive method):
#                                              -----cv2.ADAPTIVE_THRESH_MEAN_C:领域内均值
#                                              -----cv2.ADAPTIVE_THRESH_GAUSSIAN_C:领域内像素点加权和,权重为一个高斯窗口
# 第四个值的赋值方法:只有cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV
# 第五个Block size:设定领域大小(一个正方形的领域)
# 第六个参数C,阈值等于均值或者加权值减去这个常数(为0相当于阈值,就是求得领域内均值或者加权值)
# 这种方法理论上得到的效果更好,相当于在动态自适应的调整属于自己像素点的阈值,而不是整幅图都用一个阈值
th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 5, 2)
th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
th4 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
cv2.imshow('img', img)
cv2.imshow('th1', th1)
cv2.imshow('th2', th2)
cv2.imshow('th3', th3)
cv2.imshow('th4', th4)
cv2.waitKey(0)
cv2.destroyAllWindows()


对于第五个参数的窗口越来越小时,发现得到的图像越来越细了,可以设想,如果把窗口设置的足够大的话(不能超过图像大小),那么得到的结果可能就和第二幅图像的相同了。

(三)Otsu's二值化

cv2.threshold( )函数有两个返回值,一个是阈值,第二个是处理后的图像矩阵。

前面对于阈值的设定上,我们选择的阈值都是127,在实际情况中,有的图像阈值不是127得到的图像效果更好。那么这里就需要算法自己去寻找一个阈值,而Otsu's就可以自己找到一个认为最好的阈值。并且Otsu's非常适合于图像灰度直方图(只有灰度图像才有)具有双峰的情况。他会在双峰之间找到一个值作为阈值,对于非双峰图像,可能并不是很好用。那么经过Otsu's得到的那个阈值就是函数cv2.threshold的第一个参数了。因为Otsu's方法会产生一个阈值,那么函数cv2.threshold( )的第二个参数(设定阈值)就是0了,并且在cv2.threshold的方法参数中还得加上语句cv2.THRESH_OTSU.

在下列这些程序和图片中大家会有鲜明的体会:

img = cv2.imread('2.jpg', 0)
ret1, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)  # 简单滤波
ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)  # Otsu 滤波
print(ret2)
cv2.imshow('img', img)
cv2.imshow('th1', th1)
cv2.imshow('th2', th2)
# 用于解决matplotlib中显示图像的中文乱码问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.hist(img.ravel(), 256)
plt.title('灰度直方图')
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()



2018-08-26 10:09:29 lz0499 阅读数 471

                                          一种快速图像阈值处理技术

在机器视觉中,阈值处理可能是最基本的一种图像处理。阈值处理需要遍历每一帧的每一个像素以达到检测物体的目的。如果我们能够使这种遍历更加快速,那么CPU将有更多的时间处理其他任务。这篇文章将介绍一种快速阈值处理技术--减少遍历时间的方法。

常规方法:

阈值处理的常规方法中,我们遍历每一个通道的每一个像素值是否处于一定范围内。伪代码如下:

if (redcomponent > somevalue1 &&

    redcomponent < somevalue2 &&

    greencomponent > somevalue3 &&

    greencomponent < somevalue4 &&

    bluecomponent > somevalue5 &&

    bluecomponent < somevalue6)

{

    // Do something (like mark it as white)

}

这种方法的缺陷是:它进行了六次比较----太多了。另一个缺陷是分子太多了,需要处理器经常跳转处理分支。如下图所示,表示的是RGB三通道进行比较的常规方法:

 

新方法:

之前的方法主要问题是对每一个通道进行了两次比较。但是每一次比较总是固定的数值进行比较。比如,对于红色通道而言,比较范围总是从value1到value2。因此,我们有如下方法:

我们可以创建一个拥有256个元素的数组或查找表。把value1到value2的范围设置为1,其他index的值设置为0,类似的,其他两个通道也是可以这样处理的。如下图所示:

 现在,假设需要判断某一个像素的灰度值大小是否在某一范围内,我们可以使用如下伪代码表示:

if(table_red[redcomponent] &&
    table_green[greencomponent] &&
    table_blue[bluecomonent])
{
    // do something
}

假如红色通道的某一像素灰度值在value1到value2之间,table的值将为1,否则为0.类似的,其他两个通道也是这样处理。如果颜色在正确的范围内,判断条件总为真。因此,你可以把相应的像素做任何你想做的事。

很简单不是。典型的空间换时间的方法。在OpenCV中已经使用了这种技术,并利用相应的处理器指令提高阈值处理速度了。其他领域可以借鉴下。

实验结果:

使用常规方和OpenCV所使用的新方法,对比结果如下:

Image size (pixels) Standard (ms) Super fast method (ms)
73902 1.278624 0.394651
636000 5.791450 2.213925
1555200 13.664513 5.687084

 从对比结果可以看出来,新方法将近有300%的的提速。

参考资料:

super fast thresholding technique