OpenCV:入门(二)

阈值处理

阈值处理是指剔除图像内像素值高于一定值或者低于一定值的像素点。

一,Threshold函数

retval, dst = cv2.threshold( src, thresh, maxval, type )

retval 代表返回的阈值。

dst 代表阈值分割结果图像,与原始图像具有相同的大小和类型。

src 代表要进行阈值分割的图像,可以是多通道的,8 位或 32 位浮点型数值。

thresh 代表要设定的阈值。

maxval 代表当 type 参数为 THRESH_BINARY 或者 THRESH_BINARY_INV 类型时,需 要设定的最大值。

type 代表阈值分割的类型 。

cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0
cv2.THRESH_BINARY_INV THRESH_BINARY的反转
cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变
cv2.THRESH_TOZERO 大于阈值部分不改变,否则取0
cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转

(1)二值化阈值处理(cv2.THRESH_BINARY)

import cv2
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
    img = cv2.imread('street.jpg',cv2.IMREAD_GRAYSCALE)
    ret,threshold1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    plt.subplot(231), plt.imshow(img,"gray"), plt.title("Origin")
    plt.subplot(232),plt.imshow(threshold1,"gray"),plt.title("THRESH_BINARY")
    plt.show()
    cv2.waitKey(0)

二值化阈值处理就是两极化,超过阈值置maxval,低于阈值置零,特别地,如果maxval = 255,那么灰度图片会直接变成黑白照片,即图片数组只有0,255组成,由图片也可以看出来,黑的更黑,白的更白。

(2)反二值化阈值处理(cv2.THRESH_BINARY_INV)

import cv2
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
    img = cv2.imread('street.jpg',cv2.IMREAD_GRAYSCALE)
    ret,threshold1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    ret,threshold2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
    plt.subplot(231), plt.imshow(img,"gray"), plt.title("Origin")
    plt.subplot(232),plt.imshow(threshold1,"gray"),plt.title("THRESH_BINARY")
    plt.subplot(233),plt.imshow(threshold2,"gray"),plt.title("THRESH_BINARY_INV")
    plt.show()
    cv2.waitKey(0)

对比2,3幅图片:Thresh_Binary_Inv实质上就是Thresh_Binary的反转。

(3)截断阈值化处理(cv2.THRESH_TRUNC)

截断就是超过阈值按阈值算,其他不变 

import cv2
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
    img = cv2.imread('street.jpg',cv2.IMREAD_GRAYSCALE)
    ret,threshold1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    ret,threshold2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
    ret,threshold3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
    plt.subplot(231), plt.imshow(img,"gray"), plt.title("Origin")
    plt.subplot(232),plt.imshow(threshold1,"gray"),plt.title("THRESH_BINARY")
    plt.subplot(233),plt.imshow(threshold2,"gray"),plt.title("THRESH_BINARY_INV")
    plt.subplot(234),plt.imshow(threshold3,"gray"),plt.title("THRESH_TRUNC")
    plt.show()
    cv2.waitKey(0)

(4)低阈值零处理(cv2.THRESH_TOZERO) 

 低阈值零处理会将图像中小于或等于阈值的像素点的值处理为 0,大于阈值的像素点的值 保持不变。

import cv2
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
    img = cv2.imread('street.jpg',cv2.IMREAD_GRAYSCALE)
    ret,threshold1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    ret,threshold2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
    ret,threshold3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
    ret,threshold4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
    plt.subplot(231), plt.imshow(img,"gray"), plt.title("Origin")
    plt.subplot(232),plt.imshow(threshold1,"gray"),plt.title("THRESH_BINARY")
    plt.subplot(233),plt.imshow(threshold2,"gray"),plt.title("THRESH_BINARY_INV")
    plt.subplot(234),plt.imshow(threshold3,"gray"),plt.title("THRESH_TRUNC")
    plt.subplot(235),plt.imshow(threshold4,"gray"),plt.title("THRESH_TOZERO")
    plt.show()
    cv2.waitKey(0)

(5)反二值化阈值处理(cv2.THRESH_BINARY_INV)

超阈值零处理会将图像中大于阈值的像素点的值处理为 0,小于或等于该阈值的像素点的 值保持不变。

import cv2
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
    img = cv2.imread('street.jpg',cv2.IMREAD_GRAYSCALE)
    ret,threshold1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    ret,threshold2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
    ret,threshold3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
    ret,threshold4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
    ret,threshold5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)
    plt.subplot(231), plt.imshow(img,"gray"), plt.title("Origin")
    plt.subplot(232),plt.imshow(threshold1,"gray"),plt.title("THRESH_BINARY")
    plt.subplot(233),plt.imshow(threshold2,"gray"),plt.title("THRESH_BINARY_INV")
    plt.subplot(234),plt.imshow(threshold3,"gray"),plt.title("THRESH_TRUNC")
    plt.subplot(235),plt.imshow(threshold4,"gray"),plt.title("THRESH_TOZERO")
    plt.subplot(236),plt.imshow(threshold5,"gray"),plt.title("THRESH_TOZERO_INV")
    plt.show()
    cv2.waitKey(0)

二,自适应阈值处理

对于色彩均衡的图像,直接使用一个阈值就能完成对图像的阈值化处理。但是,有时图像的色彩是不均衡的,此时如果只使用一个阈值,就无法得到清晰有效的阈值分割结果图像。有一种改进的阈值处理技术,其使用变化的阈值完成对图像的阈值处理,这种技术被称为自适应阈值处理。在进行阈值处理时,自适应阈值处理的方式通过计算每个像素点周围临近区域的加权平均值获得阈值,并使用该阈值对当前像素点进行处理。与普通的阈值处理方法比, 自适应阈值处理能够更好地处理明暗差异较大的图像。  

dst = cv.adaptiveThreshold( src, maxValue, adaptiveMethod, thresholdType, blockSize, C )  

  • dst 代表自适应阈值处理结果。
  • src 代表要进行处理的原始图像。需要注意的是,该图像必须是 8 位单通道的图像。
  • maxValue 代表最大值。
  • adaptiveMethod 代表自适应方法。
  • thresholdType 代 表 阈 值 处 理 方 式 , 该 值 必 须 是 cv2.THRESH_BINARY 或者 cv2.THRESH_BINARY_INV 中的一个。
  • blockSize 代表块大小。表示一个像素在计算其阈值时所使用的邻域尺寸,通常为 3、5、 7 等。
  • C 是常量。

函数 cv2.adaptiveThreshold()根据参数 adaptiveMethod 来确定自适应阈值的计算方法,函数 包含 cv2.ADAPTIVE_THRESH_MEAN_C 和 cv2.ADAPTIVE_THRESH_GAUSSIAN_C 两种不 同的方法。这两种方法都是逐个像素地计算自适应阈值,自适应阈值等于每个像素由参数 blockSize 所指定邻域的加权平均值减去常量 C。两种不同的方法在计算邻域的加权平均值时所 采用的方式不同:

cv2.ADAPTIVE_THRESH_MEAN_C:邻域所有像素点的权重值是一致的。  cv2.ADAPTIVE_THRESH_GAUSSIAN_C:与邻域各个像素点到中心点的距离有关,通 过高斯方程得到各个点的权重值。 

import cv2
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
    img = cv2.imread('street.jpg',cv2.IMREAD_GRAYSCALE)
    adaptive_mean = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,5,3)
    adaptive_gaussian = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,5,3)
     plt.subplot(121), plt.imshow(adaptive_mean), plt.title("MEAN")
     plt.subplot(122),plt.imshow(adaptive_gaussian),plt.title("GAUSS")
     plt.show()
     cv2.waitKey(0)

三,Otsu处理

在使用函数 cv2.threshold()进行阈值处理时,需要自定义一个阈值,并以此阈值作为图像 阈值处理的依据。通常情况下处理的图像都是色彩均衡的,这时直接将阈值设为 127 是比较合 适的。 但是,有时图像灰度级的分布是不均衡的,如果此时还将阈值设置为 127,那么阈值处理 的结果就是失败的。

例如,有一个图像 img,里面的像素值为:

 此时,如果仍然以 127 作为阈值,那么阈值处理结果是:

很显然,这不是我们想要的结果。我们可以观察到,对于 img,如果以阈值 125 进行分割, 可以得到较好的结果:

但是,实际处理的图像往往是很复杂的,不太可能像上述 img 那样,一眼就观察出最合适 的阈值。如果一个个去尝试,工作量无疑是巨大的。  

所以,Otsu处理的作用来了,Otsu 方法能够根据当前图像给出最佳的类间分割阈值。简而言之,Otsu 方法会遍历所有可能阈值,从而找到最佳的阈值。

img = np.zeros((5, 5), dtype=np.uint8)
img[0:6, 0:6] = 123
img[2:6, 2:6] = 126
print("img=\n", img)
t1, thd = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
print("thd=\n", thd)
t2, otsu = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
print("otsu=\n", otsu)

 

 

相关推荐

  1. openCV入门

    2024-05-25 18:41:29       34 阅读
  2. OpenCV 入门教程

    2024-05-25 18:41:29       24 阅读
  3. OpencV入门讲解

    2024-05-25 18:41:29       31 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-05-25 18:41:29       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-25 18:41:29       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-25 18:41:29       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-25 18:41:29       18 阅读

热门阅读

  1. pytorch学习(四):Dataloader使用

    2024-05-25 18:41:29       13 阅读
  2. torchdata pytorch2.3 报错

    2024-05-25 18:41:29       8 阅读
  3. bash关闭按tab两次才显示关闭按tab显示隐藏文件

    2024-05-25 18:41:29       11 阅读
  4. bash中的通配符小结

    2024-05-25 18:41:29       11 阅读
  5. Android 15 将引入强大的手机防盗防偷体验

    2024-05-25 18:41:29       8 阅读
  6. Mac m1安装AWVS

    2024-05-25 18:41:29       12 阅读