OpenCv 中的【图像阈值化处理】

正常一个图像分为 R、G、B、三个通道,彩色照片中的每个像素值(生活中的某一中颜色)都是由不同R、G、B的值组合在一起的,比如下面这种:

而 图片去色之后变成灰度图,也就是我们所常见的黑白照片,其实生活中所谓的 "黑白照片"有一定的歧义,仔细观察会发现里面会参杂着不同程度的灰色:

真正意义上的 黑白照片 中只有黑色跟白色,要么是白色,要么是黑色;把一张灰度图变成这样的 黑白照片 也称之为 图像的 二值化

图像的二值化一般经过下面几个步骤:

  • 图像灰度图转化,多通道变单通道;
  • 设置阈值,在设置一个新值(介于黑—白之间的颜色),高于这个颜色设为新值,否则设为另外一个颜色;
  • 选择调节方法阈值;

OpenCv 中有分为几类阈值:简单阈值、自适应阈值和 Otsu’s 二值化,其实这几种方法都是关于图像二值化处理:

简单阈值


简单阈值原理,设置一个阈值,高于这个阈值的图像赋予一个新值,低于这个阈值赋予另一种颜色,用到的函数主要是 cv2.threshhold();里面需要用到4个参数:第一个是需要处理的原图像;第二个是 设置的阈值,第三个是需要赋予的新的像素值;第四个参数是 不同的阈值方法:

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

五种阈值方法区别如下:

为了让大家更加理解,这里分别用每种阈值方法来处理原图像,代码如下:

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

img_path = 'D:/ceshi.jpg'


img = cv2.imread(img_path)
#灰度图转化;;;
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)


ret,th1 = cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY)
ret,th2 = cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY_INV)
ret,th3 = cv2.threshold(img_gray,127,255,cv2.THRESH_TRUNC)
ret,th4 = cv2.threshold(img_gray,127,255,cv2.THRESH_TOZERO)
ret,th5 = cv2.threshold(img_gray,127,255,cv2.THRESH_TOZERO_INV)

titles = ['oringnal','gray_img','BINGARY','BINGARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img,img_gray,th1,th2,th3,th4,th5]
i = 0
for i in range(7):
    plt.subplot(3,3,i+1)
    plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

plt.show()

阈值展示效果如下:

可以从图像中可以很清楚地看到 不同阈值之间的区别与联系;Threshold()函数返回的有两个值,第二个才是我们要的图像

自适应阈值


这一部分选取处理图像如下:

简单阈值又称之为全句阈值,就是整个图像发生改变,图像中的像素值分布只有两种,一种是大于初设的阈值区域,另外一种就是小于初设的阈值,对于图像阈值处理方面具有一定的局限性,OpenCv 中又引入了一种 自适应阈值 方法,使得图像中不同亮度部分最终显示不同效果,

**自适应阈值 ** 是根据图像上 每一小区域来进行计算 其对应阈值,也就是不同区域会设置不同的阈值效果,

OpenCv 中 自适应阈值函数用到的函数为: adaptiveThreshold(),里面包含有6个参数:

  • 第一个跟简单阈值一样,是源图像 img;

  • 第二个就是赋予的新像素值;

  • 第三个为 Adaptive Method 指定计算阈值的方法,有两种:

    • cv2.ADPTIVE_THRESH_MENA_C:阈值取子相邻区域的平均值;
    • cv2.ADPTOVE_THRESH_GAUSSIAN_C:阈值取值相邻区域的加权和,权重为一个高斯窗口。
  • 第四个就是需要选用的阈值方法,简单阈值中用到过的,例如:cv2.THRESH_BINARY

  • 第五个参数为 Block Size —邻域大小(用来计算阈值的区域大小)。

  • 第六个参数 C 是一个常数,阈值就等于的平均值或者加权平均值减去这个常数值;

提醒一下,在做 自适应阈值 之前,需要对图片进行 一下 中值滤波处理 ;计算指定大小区域的平均像素值并把这一区域的像素值统一赋值;

下来可以看一下 自适应阈值简单阈值 之间的区别,以及 自适应阈值 不同计算方法之间的差别:

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


#图片读入灰度图
img1  =cv2.imread('E:/7.jpg',0)
#中值滤波
img = cv2.medianBlur(img1,5)
#简单阈值
ret, th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,
                            cv2.THRESH_BINARY,11,2)
th3 =cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,
                           cv2.THRESH_BINARY,11,5)



th4 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)

th5 =cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,5)

titles = [
    'origianl_ images','means-image','gloabal(v = 127)','Mean(C =2)',
'Mean(C =5)','Gayssian(C = 2)',
'Gayssian(C = 5)'
]


images =[img1,img,th1,th2,th3,th4,th5]

num = 1
for i in range(2,6):
    plt.subplot(2,2,num),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
    num += 1

plt.show()

展示效果:

这里我用到的图片比较模糊,所以展示的效果很差,下面我贴一下官网上的效果图:

效果看起来不错吧!

Otsu’s 二值化


无论是 简单阈值 ,还是 自适应阈值 ,我们在处理之前都不可避免地需要考虑 阈值 设置问题,设置的好坏对于最后成像起到很大的影响,但是怎样设置一最适合的阈值呢?不断尝试?

而这个就是 Ostu 二值化要做的,通过根据图像的直方图分布计算出一个阈值 ,但是对于 非双峰图像来说,这种方法得到的结果可能不太理想,Ostu 二值化 用到的函数同样是 cv2.threshold(),

在之前的 简单阈值 部分中,cv2.threshold() 函数返回了两个值,第二个参数是我们最后要的图像,而第一个 rerval ,其实就是这里我们要计算的的最佳阈值,Ostu二值化 与 **简单阈值 **之间 一个重要的区别,就是需要多传入一个参数:cv2.THRESH_OSTU ,同时把 threshold() 函数中设定的阈值一定要设为 0;

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


#图片读入灰度图
img1  =cv2.imread('E:/9.jpg',0)

#简单阈值处理
ret1,th1 = cv2.threshold(img1,127,255,cv2.THRESH_BINARY)

#Ostu thresholding
ret2,th2 = cv2.threshold(img1,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)


# Ostu ‘ s thresholding after Gaussian FILTERING
#5,5为高斯核的大小,0为标准差;
blur =cv2.GaussianBlur(img1,(5,5),0)

ret3,th3 =cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

## plot all the images and their histogram
images =[img1,0,th1,
         img1,0,th2,
         blur,0,th3]
titles =[

    'Ori','Hist','Glo(v =127)',
    'Ori', 'Hist', 'Ostu',

    'Gass', 'Hist', 'Ostu',

]
#治理使用 pyplot绘制直方图,参数为一维数组,用到了numpy.ravel()函数;

for i in range(3):
    plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
    plt.title(titles[i*3]),plt.xticks([]),plt.yticks([])
    plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
    plt.title(titles[i*3+1]),plt.xticks([]),plt.yticks([])
    plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')
    plt.title(titles[i*3+2]),plt.xticks([]),plt.yticks([])
plt.show()

这里选取一个带有噪点的图像,对于第一、二排是分别对图像做了 简单阈值Ostu二值化 ,而对于第三副图,先对带噪点的图像做了一个高斯核出去噪音,然后再进行 二值化

下面利用 pyplot 函数展示每一排分别代表为:处理之前的图像、未处理的直方图、处理之后的图像;

因为这里处理的元图像很模糊,所以处理之后的效果并不明显,这里贴一张官方的图片:

怎么样是不是很赞,而我处理的原图像就下面这样子。。。。。:

个人微信公众号:Z先生点记,没事常来做做。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员大飞1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值