9.3Otsu阈值分割

基本概念

在OpenCV中,Otsu阈值分割是一种全局阈值分割方法,但它会自动选择一个最佳的阈值来分割图像,这个阈值是通过最小化类内方差或等价地最大化类间方差来确定的。OpenCV提供了cv::threshold函数来实现这一功能,其中可以指定cv::THRESH_OTSU作为阈值类型之一。

OpenCV中的Otsu阈值分割

要使用Otsu阈值分割,你需要将cv::threshold函数的thresh参数设置为0(因为Otsu算法会自动计算阈值),并将maxval参数设置为当像素值超过(或小于,取决于threshType)阈值时应该赋予的新值,然后将threshType设置为cv::THRESH_BINARY | cv::THRESH_OTSU。注意,虽然cv::THRESH_OTSU是一个标志,但你需要将它与实际的阈值类型(如cv::THRESH_BINARY)组合使用。

Otsu阈值分割是一种广泛使用的全局阈值选择方法,它自动选择一个阈值来将图像分成两部分:前景和背景。这种方法基于最大类间方差的原则来寻找最优的单阈值,从而将图像二值化。

函数原型

对于cv::threshold函数中与Otsu相关的部分,其原型可以简化为:

double cv::threshold(InputArray src, OutputArray dst,   double thresh, double maxval, int thresholdType)但当你使用Otsu阈值时,thresh参数实际上会被忽略,因为它将由算法自动计算。你主要关心的是返回的阈值(如果thresholdType包含cv::THRESH_OTSU),它可以通过函数的返回值获得。

Otsu's二值化方法是一种自动计算图像最佳阈值的技术,它常用于图像分割。这种方法的目标是找到一个阈值,使得图像分割成前景和背景两部分之后,这两部分之间的类间方差最大。简而言之,Otsu's方法试图找到一个全局阈值,将图像像素分为两个类(前景和背景),使得它们之间的差异最大化。

在OpenCV中,你可以使用cv::threshold函数来应用Otsu's阈值分割。

以下是如何在C++中使用OpenCV实现Otsu's阈值分割的步骤:
步骤 1: 包含必要的头文件
首先,你需要包含OpenCV的头文件。#include <opencv2/opencv.hpp>
using namespace cv;步骤 2: 加载图像
加载你要处理的灰度图像。如果你有一个彩色图像,需要先将其转换为灰度图像。
Mat src = imread("path_to_your_image.jpg", IMREAD_GRAYSCALE);
if (src.empty()) {std::cout << "Error opening image" << std::endl;return -1;
}步骤 3: 应用Otsu's阈值分割
使用cv::threshold函数设置threshold参数为0,并且传递THRESH_BINARY + THRESH_OTSU标志。int thresholdValue = 0;
Mat dst;
threshold(src, dst, thresholdValue, 255, THRESH_BINARY + THRESH_OTSU);这里,thresholdValue设置为0是因为Otsu's算法会根据图像的直方图自动计算最佳阈值。255是超过阈值后的最大值,对于黑白二值化来说通常就是白色。步骤 4: 显示结果
显示原始图像和处理后的图像。
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", src);namedWindow("Otsu's Binarization", WINDOW_NORMAL);
imshow("Otsu's Binarization", dst);waitKey(0);

完整示例代码1

以下是完整的示例代码:

#include <opencv2/opencv.hpp>
#include <iostream>int main(int argc, char** argv) {cv::Mat src = cv::imread("path_to_your_image.jpg", cv::IMREAD_GRAYSCALE);if (src.empty()) {std::cout << "Error opening image" << std::endl;return -1;}int thresholdValue = 0;cv::Mat dst;cv::threshold(src, dst, thresholdValue, 255, cv::THRESH_BINARY + cv::THRESH_OTSU);cv::namedWindow("Original Image", cv::WINDOW_NORMAL);cv::imshow("Original Image", src);cv::namedWindow("Otsu's Binarization", cv::WINDOW_NORMAL);cv::imshow("Otsu's Binarization", dst);cv::waitKey(0);return 0;
}

运行结果1

Otsu 阈值分割的实现步骤
1. 导入必要的头文件: 需要包含 OpenCV 的核心模块头文件。
#include <opencv2/opencv.hpp>
using namespace cv;2. 读取图像: 使用 imread 函数从磁盘读取图像,并将其转换为灰度图,因为 Otsu 阈值分割通常应用于灰度图像。Mat src = imread("path/to/image.jpg", IMREAD_GRAYSCALE);
if (src.empty()) {std::cout << "Error: Image not found or unable to read the image." << std::endl;return -1;
}3. 应用 Otsu 阈值分割: 使用 threshold 函数进行 Otsu 阈值分割。这里需要注意的是,需要将 THRESH_OTSU 标志添加到 threshold 函数中,以便启用 Otsu 方法。double thresholdValue;
// 选择一个初始阈值(这里设置为0),并让OpenCV计算最佳阈值
threshold(src, src, 0, 255, THRESH_BINARY + THRESH_OTSU, &thresholdValue);
THRESH_OTSU 标志告诉 threshold 函数使用 Otsu 的算法来计算最佳阈值。thresholdValue 是一个输出参数,它将返回计算出的最佳阈值。4. 显示结果: 可以通过 imshow 显示原始图像和处理后的图像,并等待用户按键退出。namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", src);namedWindow("Otsu Threshold Result", WINDOW_NORMAL);
imshow("Otsu Threshold Result", src);waitKey(0); // Wait for a keystroke in the window
5. 获取并打印阈值(可选): 如果需要查看计算出的最佳阈值,可以在程序中打印出来。
std::cout << "The optimal threshold value is: " << thresholdValue << std::endl;

完整的示例代码2

#include "pch.h"#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main() {// 读取图像Mat src = imread("654.png", IMREAD_GRAYSCALE);if (src.empty()) {cout << "Error: Image not found or unable to read the image." << endl;return -1;}// 应用 Otsu 阈值分割double thresholdValue;Mat dst;thresholdValue=threshold(src, dst, 0, 255, THRESH_BINARY + THRESH_OTSU);// 显示结果namedWindow("Original Image", WINDOW_NORMAL);imshow("Original Image", src);namedWindow("Otsu Threshold Result", WINDOW_NORMAL);imshow("Otsu Threshold Result", dst);// 打印阈值cout << "The optimal threshold value is: " << thresholdValue << endl;waitKey(0); // Wait for a keystroke in the windowreturn 0;
}注意事项
•Otsu 阈值分割适用于双峰直方图的图像,即图像中前景和背景有明显的灰度差异。
•如果图像的直方图没有明显的双峰分布,Otsu 阈值分割可能不会得到满意的结果。
•对于光照不均匀或背景复杂的图像,可能需要结合其他预处理技术(如直方图均衡化)来改善分割效果。

运行结果2

示例代码3

下面是一个使用OpenCV C++ API进行Otsu阈值分割的示例代码:

#include <opencv2/opencv.hpp>  
#include <iostream>  using namespace cv;  
using namespace std;  int main() {  // 加载图像  Mat src = imread("path_to_image.jpg", IMREAD_GRAYSCALE);  if (src.empty()) {  cout << "Could not open or find the image!\n";  return -1;  }  // 创建输出图像  Mat dst;  // 应用Otsu阈值分割  // 注意:thresh被设置为0,因为Otsu会自动计算它  // maxval是超过阈值时要赋予的新像素值  // THRESH_BINARY | THRESH_OTSU表示使用Otsu算法进行二值化  double threshVal = threshold(src, dst, 0, 255, THRESH_BINARY | THRESH_OTSU);  // 输出计算得到的阈值  cout << "Calculated threshold value with Otsu's method: " << threshVal << endl;  // 显示结果  imshow("Original Image", src);  imshow("Otsu Thresholding", dst);  waitKey(0);  return 0;  
}

在这个示例中,我们加载了一个灰度图像,并使用Otsu算法对其进行了二值化处理。计算得到的阈值通过threshold函数的返回值获得,并打印到控制台上。然后,我们显示了原始图像和分割后的图像。

运行结果3

请注意,Otsu阈值分割适用于具有明显双峰直方图的图像,即图像的前景和背景在像素值上差异较大,且它们的分布相对独立。如果图像的直方图不满足这些条件,Otsu算法可能无法提供最佳结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/146461.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

线段树-认识线段树+实现线段树

一、认识线段树 1、定义 线段树是平衡二叉树 2、特点 线段树将一个区间划分成单元区间&#xff0c;每个单元区间对应线段树中的一个结点 3、应用 频繁查找一个数组中指定区间内的和、最值 学了动态规划后使用迭代要好过使用递归&#xff0c;因为递归每次进去是有空间损耗…

如何在qtcreator debugger上运行gdb命令

How to run gdb commands from qtcreator debugger? | Qt Forum gdb 调试基础操作和在qtcreator中使用gdb调试_qt gdb-CSDN博客 输出变量名&#xff1a; p变量名 ------------ gdb调试技巧&#xff08;二&#xff09;———— gdb 条件断点_gdb设置带函数入参判断的条件断点…

UE Asset Batch Duplication插件

目录 准备工作 "Scripting library" 三个最重要的功能&#xff08;前两个是UEditorUtilityLibrary中的&#xff09; 自动创建声明&#xff1a; TArray T 的含义 F 的含义 Live Coding &#xff08;Ctrlalt F11&#xff09; Live Coding 的工作流程&#xff…

时序预测|基于灰狼优化LightGBM的时间序列预测Matlab程序GWO-LightGBM 单变量和多变量 含基础模型

时序预测|基于灰狼优化LightGBM的时间序列预测Matlab程序GWO-LightGBM 单变量和多变量 含基础模型 文章目录 一、基本原理原理概述流程注意事项 二、实验结果三、核心代码四、代码获取五、总结 一、基本原理 时序预测中使用灰狼优化&#xff08;GWO&#xff09;结合LightGBM的…

Hash-通过哈希桶解决Hash冲突

哈希桶 基本结构 template<class T> struct HashNode {T _data;HashNode<T>* _next; }; template<class K,class T,class KeyOfT> class HashTable {typedef HashNode<T> Node; public:private:vector<Node*> _tables;size_t _num; }; insert …

《飞机大战游戏》实训项目(Java GUI实现)(设计模式)(简易)

目录 一、最终实现后&#xff0c;效果如下。 &#xff08;1&#xff09;简单介绍本游戏项目&#xff08;待完善&#xff09; &#xff08;2&#xff09;运行效果图&#xff08;具体大家自己可以试&#xff09; 初始运行情况。 手动更换背景图。 通过子弹攻击敌机&#xff0c;累…

java之单链表的基本概念及创建

1.链表的概念: 链表是一种 物理存储结构上非连续 存储结构&#xff0c;数据元素的 逻辑顺序 是通过链表中的 引用链接 次序实现的 。 组成结构: 由一系列节点组成&#xff0c;每个节点包含数据域和指向下一个节点的指针。 优点: 动态大小&#xff0c;易于插入和删除操作。 缺点…

无人机集群路径规划:​北方苍鹰优化算法(Northern Goshawk Optimization,NGO)​求解无人机集群路径规划,提供MATLAB代码

一、单个无人机路径规划模型介绍 无人机三维路径规划是指在三维空间中为无人机规划一条合理的飞行路径&#xff0c;使其能够安全、高效地完成任务。路径规划是无人机自主飞行的关键技术之一&#xff0c;它可以通过算法和模型来确定无人机的航迹&#xff0c;以避开障碍物、优化…

51单片机——LED灯篇

一、LED与单片机P2管脚相连 二、点亮一个LED灯 #include <STC89C5xRC.H> void main() { P2 0xFE; //1111 1110 } P2有8个管脚&#xff0c;对应8个二进制位。 LED灯右侧接电源是正极&#xff08;1&#xff09;&#xff0c;左侧给负极&#xff08;0&#xff09;即可…

Web_php_include 攻防世界

<?php show_source(__FILE__); echo $_GET[hello]; $page$_GET[page]; while (strstr($page, "php://")) { 以是否检测到php://为判断执行循环$pagestr_replace("php://", "", $page);//传入空值&#xff0c;替换 } include($page); ?&g…

第四范式发布AIGS Builder企业级软件重构助手,以生成式AI重构企业软件

产品上新 Product Release 今天&#xff0c;第四范式发布企业级软件重构助手——AIGS Builder&#xff0c;可快速重构软件交互体验。传统的企业软件开发&#xff0c;每次迭代通常要以月计。基于第四范式AIGS Builder大模型&#xff0c;用生成式Agent替代复杂的界面&#xff0c;…

AI绘制调整虚线教程

1、打开ai的软件&#xff0c;执行菜单栏中的文件—新建&#xff0c;新建一个大小任意的画板&#xff0c;画板大小根据自己的需要来设置。 2、选择工具箱中的直线段工具&#xff0c;将填充设置为无&#xff0c;描边设置为黑色&#xff0c;描边大小稍微设置大一点&#xff0c;画一…

模拟实现STL的stack、queue、deque等的介绍

文章目录 前言一、模拟实现stack二、模拟实现queue三、 deque总结 前言 模拟实现STL的stack、queue、deque等的介绍 一、模拟实现stack STL的stack是通过增加一个容器的模板参数&#xff0c;不直接实现栈&#xff0c;让容器存储数据&#xff0c;并调用容器的接口实现栈 name…

环形链表问题——力扣141,142

环形链表问题——力扣141&#xff0c;142 141.判断链表是否带环142.给定一个链表&#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 NULL 141.判断链表是否带环 这道题不能用比较链表中的值来判断是否带环&#xff0c;因为链表中不同节点的值可以相同…

Java免税购物商城:Spring Boot技术实现

第二章 系统开发关键技术 2.1 JAVA技术 Java主要采用CORBA技术和安全模型&#xff0c;可以在互联网应用的数据保护。它还提供了对EJB&#xff08;Enterrise JavaBeans&#xff09;的全面支持&#xff0c;java servlet AI&#xff0c;JS&#xff08;java server ages&#xff09…

matlab绘制二维云图,划分区域,并显示每个区域的均值

绘制成图如下&#xff1a; 代码如下&#xff1a; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%创建绘图的数据 ax0;bx1; ay0;by1; nx100; %数据的x轴点数 ny100; %数据的y轴点数 hx(bx-ax)/(nx-1); hy(by-ay)/(ny-1); Xax:hx:bx; Yay:hy:by; da…

有趣的Python-turtle

1 介绍 turtle 是 Python 中用来绘图的标准库&#xff08;Python解释器在安装后import直接使用&#xff09;&#xff0c;它简单且有趣&#xff0c;作为 Python初学者 都可以将它作为第一个学习对象&#xff0c;培养程序学习的兴趣&#xff0c;建立编程带来的成就感&#xff0c…

网络安全-webshell绕过,hash碰撞,webshell绕过原理

目录 一、题目 1.1 1.2 1.3 1.4 1.5 二、绕过动态检测引擎的一次尝试 三、一个比赛中的webshell 四、webshell绕过的原理以及哈希碰撞 五、JSP解释流程导致的绕过&#xff08;QT比赛&#xff09; 5.1环境 5.2例子 一、题目 这里我们通过几道题目来给大家讲解 1.…

Springboot3 + MyBatis-Plus + MySql + Uniapp 实现商品规格选择sku(附带自设计数据库,最新保姆级教程)

Springboot3 MyBatis-Plus MySql Uniapp 实现商品规格选择sku&#xff08;附带自设计数据库&#xff0c;最新保姆级教程&#xff09; 1、效果展示2、数据库设计2.1 商品表2.2 商品价格和规格中间表2.3 商品规格表 3、后端代码3.1 model3.2 vo3.3 mapper、server、serverImp3…

前端-javaScript:jquery补充

jquery绑定事件的方式 1.直接使用事件函数 &("div").click(function(){alert(1)}) 2.用统一的on函数绑定事件 on(事件类型&#xff0c;事件函数) $("div").on("click",function(){alert(2)}) 事件类型以参数的类型传递 --->可以同时绑…