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

server/2025/1/23 18:41:42/

【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.ppmy.cn/server/160817.html

相关文章

Golang的图形编程基础

Golang的图形编程基础 一、Golang对图形编程的支持 语言是一种优雅的、简洁的编程语言,它在图形编程领域也有着广泛的应用。Golang通过一些第三方库和工具支持图形编程,开发者可以利用这些工具来创建丰富多彩的图形界面和可视化效果。 是一个使用Go语言编…

STM32-CAN总线

1.CAN总线简介 CAN总线是由BOSCH公司开发的一种简洁易用、传输速度快、易扩展、可靠性高的串行通信总线 2.CAN总线特征 两根通信线(CAN_H、CAN_L),线路少,无需共地差分信号通信(相对的是单端信号)&#…

NodeJs如何做API接口单元测试? --【elpis全栈项目】

NodeJs API接口单元测试 api单元测试需要用到的 assert:断言库 (还要一些断言库比如:Chai)supertest: 模拟http请求 简单的例子: const express require(express); const supertest require(supertest); const assert require(assert);…

【Red Hat8】:搭建DHCP服务器

1、新建挂载文件 2、挂载 3、关闭防火墙 4、搭建yum源 (搭建的时候用vim 自行定义文件名.repo或者是vi 自行定义文件名.repo) 5、安装dhcp-server 6、复制模板文件 dhcpd.conf 是DHCP服务的配置文件,DHCP服务所有参数都是通过修改dhcpd.co…

澎峰科技计算软件栈与沐曦GPU完成适配和互认证

近期,澎峰科技与沐曦完成了对PerfXLM(推理引擎)、PerfXCloud(大模型服务平台)与沐曦的曦云系列通用计算GPU的联合测试,测试结果表明PerfXLM、PerfXCloud软件与沐曦GPU产品实现了全面兼容。 PerfXLM高性能大…

如何将本地 Node.js 服务部署到宝塔面板:完整的部署指南

文章简介: 将本地开发的 Node.js 项目部署到线上服务器是开发者常见的工作流程之一。在这篇文章中,我将详细介绍如何将本地的 Node.js 服务通过宝塔面板(BT 面板)上线。宝塔面板是一个强大的服务器管理工具,具有简洁的…

Windows11电脑总是一闪一闪的,黑一下亮一些怎么解决

Windows11电脑总是一闪一闪的,黑一下亮一些怎么解决 1. 打开设备管理器2. 点击显示适配器3. 更新下方两个选项的驱动3.1 更新驱动Inter(R) UHD Graphixs3.2 更新驱动NVIDIA GeForce RTX 4060 Laptop GPU 4. 其他文章快来试试吧🥰 1. 打开设备管理器 在电…

Unity3D 动态骨骼性能优化详解

前言 在Unity3D中,动态骨骼动画是创建逼真角色动画的关键技术。然而,随着骨骼数量的增加和动画复杂度的提升,性能问题也随之而来。本文将详细介绍如何在Unity3D中进行动态骨骼性能优化,并提供技术详解和代码实现。 对惹&#xf…