当前位置: 首页 > article >正文

python学opencv|读取图像(三十八 )阈值自适应处理

【1】引言

前序学习了5种阈值处理方法,包括(反)阈值处理、(反)零值处理和截断处理,相关文章链接为:

python学opencv|读取图像(三十三)阈值处理-灰度图像-CSDN博客

python学opencv|读取图像(三十四)阈值处理-彩色图像-CSDN博客

python学opencv|读取图像(三十五)反阈值处理-CSDN博客

python学opencv|读取图像(三十六)(反)零值处理-CSDN博客

python学opencv|读取图像(三十七 )截断处理-CSDN博客

经过对比,会发现零值处理获得的图像效果更为明显。

但实际上,无论是哪种处理方法,内部的阈值开关都是自由设定的,因此,难以确认零值处理是否效果总是相对较好?

这时候,我们刚好发现了一个自适应处理函数:cv.adaptiveThreshold(),这个函数允许图像按照方块大小,逐个做阈值处理,相当于是更为精细化的阈值处理方式。

【2】官网教程

点击下述链接,可以直达cv.adaptiveThreshold()函数的官网教程:

OpenCV: Miscellaneous Image Transformations

在官网,可以看到cv.adaptiveThreshold()函数的参数说明:

图1

具体的参数解释为:

void cv::adaptiveThreshold     (     InputArray     src,  #输入图像
        OutputArray     dst,                                             #输出图像
        double     maxValue,                                           #阈值上限
        int     adaptiveMethod,                                        #自适应方法
        int     thresholdType,                                           #阈值处理方法
        int     blockSize,                                                  #方块大小
        double     C )                                                       #均值或者加权均值减去的常量,一般是正整数

官网指出,自适应放大法adaptiveMethod只有两种选择:cv.THRESH_BINARY和cv.THRESH_BINARY_INV。

【3】代码测试  

cv.adaptiveThreshold()函数只能对灰度图进行自适应处理,这里我们先回忆一下灰度图生成技巧:

python学opencv|读取图像(十一)彩色图像转灰度图的两种办法_opencv读取png图片为灰度图片-CSDN博客

因此我们在设计程序时,也设计了两种灰度图转化方法,以作为对前述学习知识的复习:

 

import cv2 as cv # 引入CV模块
import numpy as np #引入numpy模块

# 读取图片-直接转化灰度图
src = cv.imread('srcf.png',0) #读取图像
dst=src#输出图像


# 读取图片-函数转化灰度图
src1 = cv.imread('srcf.png') #读取图像
dst1=cv.cvtColor(src1,cv.COLOR_BGR2GRAY) #转化为灰度图

dstt=np.hstack((dst,dst1)) #两种灰度图拼接在一起

 由于我们已经知晓了这两种方法转化后的图像效果一样,因此直接进行自适应处理,并且把零值处理加进来做对比:

#自适应处理
dstt1=cv.adaptiveThreshold(src,158,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,5,3) #
dstt2=cv.adaptiveThreshold(src,158,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,5,3) #
dsttv1=cv.adaptiveThreshold(src,158,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY_INV,5,3) #
dsttv2=cv.adaptiveThreshold(src,158,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY_INV,5,3) #
#零值处理
t2,dst2=cv.threshold(src,58,158,cv.THRESH_TOZERO) #零值-阈值开关58,阈值上限158
#dstt3=cv.adaptiveThreshold(src,158,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_TOZERO,5,3) #
dsttt=np.hstack((dstt1,dstt2)) #两种灰度图拼接在一起
dstttv=np.hstack((dsttv1,dsttv2)) #两种灰度图拼接在一起8,cv.THRESH_TOZERO) #零值-阈值开关58,阈值上限158

然后对图像进行呈现和保存:

#阈值和零值处理
#t1,dst1=cv.threshold(src,58,158,cv.THRESH_BINARY) #阈值-阈值开关58,阈值上限158
#t2,dst2=cv.threshold(src,58,158,cv.THRESH_TOZERO) #零值-阈值开关100,阈值上限255

#截断处理
#t3,dst3=cv.threshold(src,58,158, cv.THRESH_TRUNC) #截断-阈值开关158,阈值上限200

#t2,dst2=cv.threshold(src,100,255,cv.THRESH_TOZERO) #阈值开关100,阈值上限255
#t3,dst3=cv.threshold(src,0,255,cv.THRESH_TOZERO) #阈值开关0,阈值上限255

#反阈值和反零值处理
#tt1,dstt1=cv.threshold(src,58,158,cv.THRESH_BINARY_INV) #阈值开关100,阈值上限255
#tt2,dstt2=cv.threshold(src,58,158,cv.THRESH_TOZERO_INV) #阈值开关100,阈值上限255

#tt1,dstt1=cv.threshold(src,58,158,cv.THRESH_TOZERO_INV) #阈值开关58,阈值上限158
#tt2,dstt2=cv.threshold(src,100,255,cv.THRESH_TOZERO_INV) #阈值开关100,阈值上限255
#tt3,dstt3=cv.threshold(src,0,255,cv.THRESH_TOZERO_INV) #阈值开关0,阈值上限255

#和原图对比
#ttt1=np.hstack((dst,dst1,dst3)) #原图-阈值-截断对比
#ttt2=np.hstack((dst,dst2,dst3)) #原图-零值-截断对比
#ttt3=np.hstack((dst,dstt1,dst3)) #原图-反阈值-截断对比
#ttt4=np.hstack((dst,dstt2,dst3)) #原图-反零值-截断对比
#ttt5=np.hstack((dst,dst1,dst2)) #原图-阈值-零值对比
#ttt6=np.hstack((dst3,dstt1,dstt2)) #截断-反阈值-反零值对比
#ttt7=np.vstack((ttt5,ttt6)) #原图-阈值-零值-截断-反阈值-反零值对比
#展示图像
#cv.imshow('srcft0', dst)  # 在屏幕展示效果
cv.imshow('srcft', dstt)  # 在屏幕展示效果
cv.imshow('srcft2', dst2)  # 在屏幕展示效果
cv.imshow('srcftt1', dsttt)  # 在屏幕展示效果
cv.imshow('srcftt2', dstttv)  # 在屏幕展示效果
#cv.imshow('srcfttv1', dsttv1)  # 在屏幕展示效果
#cv.imshow('srcfttv2', dsttv2)  # 在屏幕展示效果
#cv.imshow('srcftt3', dstt3)  # 在屏幕展示效果
#cv.imshow('srcft3', ttt3)  # 在屏幕展示效果
#cv.imshow('srcft4', ttt4)  # 在屏幕展示效果
#cv.imshow('srcft5', ttt7)  # 在屏幕展示效果
#显示BGR值
#print("原图-dst像素数为[100,100]位置处的BGR=", dst[100, 100])  # 获取像素数为[100,100]位置处的BGR
#print("阈值-dst1像素数为[100,100]位置处的BGR=", dst1[100, 100])  # 获取像素数为[100,100]位置处的BGR
#print("零值-dst2像素数为[100,100]位置处的BGR=", dst2[100, 100])  # 获取像素数为[100,100]位置处的BGR
#print("截断-dst3像素数为[100,100]位置处的BGR=", dst3[100, 100])  # 获取像素数为[100,100]位置处的BGR
print("dstt1像素数为[100,100]位置处的BGR=", dstt1[100, 100])  # 获取像素数为[100,100]位置处的BGR
print("dsttv1像素数为[100,100]位置处的BGR=", dsttv1[100, 100])  # 获取像素数为[100,100]位置处的BGR
print("dstt2像素数为[100,100]位置处的BGR=", dstt2[100, 100])  # 获取像素数为[100,100]位置处的BGR
print("dsttv2像素数为[100,100]位置处的BGR=", dsttv2[100, 100])  # 获取像素数为[100,100]位置处的BGR

#print("dstt3像素数为[100,100]位置处的BGR=", dstt3[100, 100])  # 获取像素数为[100,100]位置处的BGR

#保存图像
cv.imwrite('srcf-dstt.png', dstt)  # 保存图像
cv.imwrite('srcf-dst1.png', dst2)  # 保存图像
cv.imwrite('srcf-dsttt.png', dsttt)  # 保存图像
cv.imwrite('srcf-dstttv.png', dstttv)  # 保存图像
#cv.imwrite('srcf-ttt1.png', dsttv1)  # 保存图像
#cv.imwrite('srcf-ttt2.png', dsttv2)  # 保存图像
#cv.imwrite('srcf-ttt3.png', dstt3)  # 保存图像
#cv.imwrite('srcf-JC-t3-VC-ttt3.png', ttt3)  # 保存图像
#cv.imwrite('srcf-JC-t3-VC-ttt4.png', ttt4)  # 保存图像
#cv.imwrite('srcf-JC-t3-VC-ttt7.png', ttt7)  # 保存图像
cv.waitKey()  # 图像不会自动关闭
cv.destroyAllWindows()  # 释放所有窗口

此处使用的原始图像为:

图2

转化后的两种灰度图为:

图3 两种方法转化的灰度图

按照自适应转化后的图像为:

图4  左cv.ADAPTIVE_THRESH_MEAN_C右cv.ADAPTIVE_THRESH_GAUSSIAN_C-cv.THRESH_BINARY阈值处理方法

图4显示了cv.ADAPTIVE_THRESH_MEAN_C和cv.ADAPTIVE_THRESH_GAUSSIAN_C应用cv.THRESH_BINARY阈值处理方法获得的两种图像,实际上看不出显著差别。

图5  左cv.ADAPTIVE_THRESH_MEAN_C右cv.ADAPTIVE_THRESH_GAUSSIAN_C-cv.THRESH_BINARY_INV阈值处理方法

图5显示了cv.ADAPTIVE_THRESH_MEAN_C和cv.ADAPTIVE_THRESH_GAUSSIAN_C应用cv.THRESH_BINARY_INV阈值处理方法获得的两种图像,实际上也看不出显著差别。

图4和图5相对来说,因为是按照相反的阈值处理方法,所以在颜色黑白上有明显的差别,相对来说,图4代表的阈值处理方法保存的细节相对更多。

之后大家一起看一下零值处理的图像:

图6 零值处理

相对来说,零值处理保留的细节多,自适应处理保留轮廓更多。

此时的完整代码为(下述代码附带了很多注释,调整“#”出现的位置,可以用来辅助测试其他阈值处理方法):

import cv2 as cv # 引入CV模块
import numpy as np #引入numpy模块

# 读取图片-直接转化灰度图
src = cv.imread('srcf.png',0) #读取图像
dst=src#输出图像


# 读取图片-函数转化灰度图
src1 = cv.imread('srcf.png') #读取图像
dst1=cv.cvtColor(src1,cv.COLOR_BGR2GRAY) #转化为灰度图

dstt=np.hstack((dst,dst1)) #两种灰度图拼接在一起

#自适应处理
dstt1=cv.adaptiveThreshold(src,158,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,5,3) #
dstt2=cv.adaptiveThreshold(src,158,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,5,3) #
dsttv1=cv.adaptiveThreshold(src,158,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY_INV,5,3) #
dsttv2=cv.adaptiveThreshold(src,158,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY_INV,5,3) #
#零值处理
t2,dst2=cv.threshold(src,58,158,cv.THRESH_TOZERO) #零值-阈值开关58,阈值上限158
#dstt3=cv.adaptiveThreshold(src,158,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_TOZERO,5,3) #
dsttt=np.hstack((dstt1,dstt2)) #两种灰度图拼接在一起
dstttv=np.hstack((dsttv1,dsttv2)) #两种灰度图拼接在一起
#阈值和零值处理
#t1,dst1=cv.threshold(src,58,158,cv.THRESH_BINARY) #阈值-阈值开关58,阈值上限158
#t2,dst2=cv.threshold(src,58,158,cv.THRESH_TOZERO) #零值-阈值开关100,阈值上限255

#截断处理
#t3,dst3=cv.threshold(src,58,158, cv.THRESH_TRUNC) #截断-阈值开关158,阈值上限200

#t2,dst2=cv.threshold(src,100,255,cv.THRESH_TOZERO) #阈值开关100,阈值上限255
#t3,dst3=cv.threshold(src,0,255,cv.THRESH_TOZERO) #阈值开关0,阈值上限255

#反阈值和反零值处理
#tt1,dstt1=cv.threshold(src,58,158,cv.THRESH_BINARY_INV) #阈值开关100,阈值上限255
#tt2,dstt2=cv.threshold(src,58,158,cv.THRESH_TOZERO_INV) #阈值开关100,阈值上限255

#tt1,dstt1=cv.threshold(src,58,158,cv.THRESH_TOZERO_INV) #阈值开关58,阈值上限158
#tt2,dstt2=cv.threshold(src,100,255,cv.THRESH_TOZERO_INV) #阈值开关100,阈值上限255
#tt3,dstt3=cv.threshold(src,0,255,cv.THRESH_TOZERO_INV) #阈值开关0,阈值上限255

#和原图对比
#ttt1=np.hstack((dst,dst1,dst3)) #原图-阈值-截断对比
#ttt2=np.hstack((dst,dst2,dst3)) #原图-零值-截断对比
#ttt3=np.hstack((dst,dstt1,dst3)) #原图-反阈值-截断对比
#ttt4=np.hstack((dst,dstt2,dst3)) #原图-反零值-截断对比
#ttt5=np.hstack((dst,dst1,dst2)) #原图-阈值-零值对比
#ttt6=np.hstack((dst3,dstt1,dstt2)) #截断-反阈值-反零值对比
#ttt7=np.vstack((ttt5,ttt6)) #原图-阈值-零值-截断-反阈值-反零值对比
#展示图像
#cv.imshow('srcft0', dst)  # 在屏幕展示效果
cv.imshow('srcft', dstt)  # 在屏幕展示效果
cv.imshow('srcft2', dst2)  # 在屏幕展示效果
cv.imshow('srcftt1', dsttt)  # 在屏幕展示效果
cv.imshow('srcftt2', dstttv)  # 在屏幕展示效果
#cv.imshow('srcfttv1', dsttv1)  # 在屏幕展示效果
#cv.imshow('srcfttv2', dsttv2)  # 在屏幕展示效果
#cv.imshow('srcftt3', dstt3)  # 在屏幕展示效果
#cv.imshow('srcft3', ttt3)  # 在屏幕展示效果
#cv.imshow('srcft4', ttt4)  # 在屏幕展示效果
#cv.imshow('srcft5', ttt7)  # 在屏幕展示效果
#显示BGR值
#print("原图-dst像素数为[100,100]位置处的BGR=", dst[100, 100])  # 获取像素数为[100,100]位置处的BGR
#print("阈值-dst1像素数为[100,100]位置处的BGR=", dst1[100, 100])  # 获取像素数为[100,100]位置处的BGR
#print("零值-dst2像素数为[100,100]位置处的BGR=", dst2[100, 100])  # 获取像素数为[100,100]位置处的BGR
#print("截断-dst3像素数为[100,100]位置处的BGR=", dst3[100, 100])  # 获取像素数为[100,100]位置处的BGR
print("dstt1像素数为[100,100]位置处的BGR=", dstt1[100, 100])  # 获取像素数为[100,100]位置处的BGR
print("dsttv1像素数为[100,100]位置处的BGR=", dsttv1[100, 100])  # 获取像素数为[100,100]位置处的BGR
print("dstt2像素数为[100,100]位置处的BGR=", dstt2[100, 100])  # 获取像素数为[100,100]位置处的BGR
print("dsttv2像素数为[100,100]位置处的BGR=", dsttv2[100, 100])  # 获取像素数为[100,100]位置处的BGR

#print("dstt3像素数为[100,100]位置处的BGR=", dstt3[100, 100])  # 获取像素数为[100,100]位置处的BGR

#保存图像
cv.imwrite('srcf-dstt.png', dstt)  # 保存图像
cv.imwrite('srcf-dst1.png', dst2)  # 保存图像
cv.imwrite('srcf-dsttt.png', dsttt)  # 保存图像
cv.imwrite('srcf-dstttv.png', dstttv)  # 保存图像
#cv.imwrite('srcf-ttt1.png', dsttv1)  # 保存图像
#cv.imwrite('srcf-ttt2.png', dsttv2)  # 保存图像
#cv.imwrite('srcf-ttt3.png', dstt3)  # 保存图像
#cv.imwrite('srcf-JC-t3-VC-ttt3.png', ttt3)  # 保存图像
#cv.imwrite('srcf-JC-t3-VC-ttt4.png', ttt4)  # 保存图像
#cv.imwrite('srcf-JC-t3-VC-ttt7.png', ttt7)  # 保存图像
cv.waitKey()  # 图像不会自动关闭
cv.destroyAllWindows()  # 释放所有窗口

【4】细节说明

自适应处理函数cv.adaptiveThreshold():

只能处理单通道的灰度图;

阈值处理方法只能选用cv.THRESH_BINARY和cv.THRESH_BINARY_INV两种阈值处理方法。

图7

【5】总结

掌握了python+opencv实现图像自适应处理的技巧。

 

 


http://www.kler.cn/a/509587.html

相关文章:

  • 【Linux系统】Ext系列磁盘文件系统二:引入文件系统(续篇)
  • AI-Talk开发板之替换唤醒词
  • MyBatisPlus学习笔记
  • pytest-instafail:让测试失败信息即时反馈
  • 【数据库】国产达梦数据库与mysql特点、区别、发展前景
  • PyTorch DAY2: 搭建神经网络
  • (三)线性代数之二阶和三阶行列式详解
  • Zilliz Cloud上新:容量提升3倍、享5折优惠,支持高精度搜索
  • STM32 FreeROTS 任务创建和删除实验(静态方法)
  • 天童教育:怎样建立稳固的亲子关系
  • 2.5G PoE交换机 TL-SE2109P 简单开箱评测,8个2.5G电口+1个10G光口(SFP+)
  • Nginx在Linux中的最小化安装方式
  • Net Core微服务入门全纪录(三)——Consul-服务注册与发现(下)
  • 2. 进阶关卡-Laagent:从零搭建你的Multi-Agent
  • DetKDS
  • 微服务学习-Nacos 作为注册中心使用
  • Transformer之Decoder
  • 上一次和英特尔的接触...
  • vim练级攻略(精简版)
  • HBase深度历险
  • 企业分类相似度筛选实战:基于规则与向量方法的对比分析
  • React+Cesium基础教程(001):创建基于React的Cesium项目及对Cesium进行基本配置
  • Zookeeper 核心知识深度解析:从选主到部署
  • python编程-OpenCV(图像读写-图像处理-图像滤波-角点检测-边缘检测)边缘检测
  • Visual Studio Code 使用 DeepSeek-V3 教程
  • NLP文档召回