opencv(4)我一定一定坚持学完啊!

本文详细介绍OpenCV中图像阈值处理的三种方法:简单阈值、自适应阈值及Otsu二值化。通过代码示例展示了如何实现不同类型的阈值处理,包括二值化、反向二值化、截断阈值等,并讨论了在不同场景下选择合适阈值的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

opencv:图像阈值

1.简单阈值
像素值高于阈值时,我们给这个像素赋予一个新值(可能是白色),否则我们给它赋予另外一种颜色(也许是黑色)。这个函数就是 cv2.threshhold()。

import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('D:/code/opencv/images/1.png')
#函数返回两个参数,一个是retval(暂时不知道是啥),一个就是阈值化后的图像
ret,thresh1=cv2.threshold(img,127,255,cv2.THRESH_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)
#超过某个阈值被置0
ret,thresh5=cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)
#低于某个值被置0
titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

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

在这里插入图片描述
2.自适应阈值
在前面的部分我们使用是全局阈值,整幅图像采用同一个数作为阈值。当时这种方法并不适应与所有情况,尤其是当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。

import  cv2 as cv
import  numpy as np
import  matplotlib.pyplot as plt

img=cv.imread('D:/code/opencv/images/1.png')
# 中值滤波
img = cv.medianBlur(img,5)
ret,th1 = cv.threshold(img,127,255,cv2.THRESH_BINARY)
#用全局阈值
#进行自适应阈值必须对图像进行二值化,我的不进行二值化就报错
gary=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
th2 = cv.adaptiveThreshold(gary,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,11,2)
#参数图像  高于阈值变成什么  阈值取自相邻区域的平均值  邻域大小  一个常数 阈值为平均值减去这个数
th3 = cv.adaptiveThreshold(gary,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,11,2)
#阈值取自相邻区域的加权和,权重为一个高斯窗口
titles = ['Original Image', 'Global Thresholding (v = 127)','Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]

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

在这里插入图片描述

3.Otsu.s二值化
在使用全局阈值时,我们就是随便给了一个数来做阈值,那我们怎么知道我们选取的这个数的好坏呢?答案就是不停的尝试。如果是一副双峰图像(简单来说双峰图像是指图像直方图中存在两个峰)呢?我们岂不是应该在两个峰之间的峰谷选一个值作为阈值?这就是 Otsu 二值化要做的。简单来说就是对一副双峰图像自动根据其直方图计算出一个阈值。(对于非双峰图像,这种方法得到的结果可能会不理想)。

import  cv2 as cv
import  numpy as np
import  matplotlib.pyplot as plt

img=cv.imread('D:/code/opencv/images/1.png')
gary=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# global thresholding 全局阈值
ret1,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
# Otsu's thresholding 二值化的图像就会出错 不晓得为啥
ret2,th2 = cv.threshold(gary,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
# Otsu's thresholding after Gaussian filtering
#(5,5)为高斯核的大小,0 为标准差
blur = cv.GaussianBlur(gary,(5,5),0) # 阈值一定要设为 0!
ret3,th3 = cv.threshold(blur,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
# plot all the images and their histograms
images = [img, 0, th1,img, 0, th2,blur, 0, th3]
titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)','Original Noisy Image','Histogram',"Otsu's Thresholding",'Gaussian filtered Image','Histogram',"Otsu's Thresholding"] # 这里使用了 pyplot 中画直方图的方法,plt.hist, 要注意的是它的参数是一维数组
# 所以这里使用了(numpy)ravel 方法,将多维数组转换成一维,也可以使用 flatten 方法
#ndarray.flat 1-D iterator over an array.
#ndarray.flatten 1-D array copy of the elements of an array in row-major order.
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()

在这里插入图片描述
这图不是双峰的 效果不好

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值