19.OpenCV图像二值化

news2025/4/2 22:04:11

OpenCV图像二值化

图像二值化(Binarization)是图像预处理中的一种常用技术,其目的是将图像中的像素值分为两个类别——通常是“前景”和“背景”或者说0和255。二值化能够简化图像信息,为后续的形态学处理、边缘检测、目标识别等任务提供基础。本文将介绍二值化的基本概念、全局二值化、三角二值化和自适应二值化的原理与实现

1. 二值化基本概念

二值化将一幅灰度图像中的像素值根据阈值 TT 分为两类:

  • 当像素值大于 TT 时,将其设为最大值(如 255);
  • 当像素值小于或等于 TT 时,将其设为最小值(如 0)。

数学上可以表示为:

g ( x , y ) = { maxValue , if  f ( x , y ) > T 0 , if  f ( x , y ) ≤ T g(x,y)=\begin{cases}\text{maxValue}, & \text{if } f(x,y) > T \\0, & \text{if } f(x,y) \leq T\end{cases} g(x,y)={maxValue,0,if f(x,y)>Tif f(x,y)T

其中f(x,y)为原始图像像素值,g(x,y) 为二值化后的像素值。

2. 全局阈值二值化

全局阈值二值化是最简单的二值化方法,它使用一个固定阈值对整幅图像进行处理。OpenCV 提供了 cv::threshold 函数来实现这一过程。

2.1 cv::threshold 函数

函数原型如下:

double threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type);
  • 返回值:函数返回所使用的阈值,当使用 THRESH_OTSUTHRESH_TRIANGLE 时,该值为计算出的最佳阈值,否则返回 thresh
  • src:输入灰度图像。
  • dst:输出二值图像。
  • thresh:阈值 TT
  • maxval:当像素值大于阈值时赋予的值(通常为 255)。
  • type
    • THRESH_BINARY:像素值大于阈值时设为最大值,否则设为 0。
    • THRESH_BINARY_INV:像素值大于阈值时设为 0,否则设为最大值。
    • THRESH_TRUNC:像素值大于阈值时设为阈值,否则保持原值。
    • THRESH_TOZERO:像素值大于阈值时保持原值,否则设为 0。
    • THRESH_TOZERO_INV:像素值大于阈值时设为 0,否则保持原值。
    • THRESH_OTSU:自动计算最佳阈值,并使用 THRESH_BINARY 进行二值化。
    • THRESH_TRIANGLE:基于直方图形状分析自动选择阈值,适用于单峰或近似单峰直方图。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main() {
    // 读取灰度图像
    Mat gray = imread("E:/image/lena.png", IMREAD_GRAYSCALE);
    if (gray.empty()) {
        cerr << "图像加载失败!" << endl;
        return -1;
    }
    imshow("原图", gray);
    Mat binary;
    // 使用不同阈值类型进行二值化
    threshold(gray, binary, 128, 255, THRESH_BINARY);
    imshow("THRESH_BINARY", binary);

    threshold(gray, binary, 128, 255, THRESH_BINARY_INV);
    imshow("THRESH_BINARY_INV", binary);

    threshold(gray, binary, 128, 255, THRESH_TRUNC);
    imshow("THRESH_TRUNC", binary);

    threshold(gray, binary, 128, 255, THRESH_TOZERO);
    imshow("THRESH_TOZERO", binary);

    threshold(gray, binary, 128, 255, THRESH_TOZERO_INV);
    imshow("THRESH_TOZERO_INV", binary);

    waitKey(0);
    destroyAllWindows();
    return 0;
}

在上述示例中使用了128作为阈值,推荐平均值作为阈值效果会好。我们使用了不同的阈值类型进行二值化,并分别显示了处理后的结果如下图。
全局二值化

3. Otsu’s 自动阈值法

当图像的灰度直方图呈双峰分布时,Otsu 自动阈值法可以自动选择最佳阈值,从而实现自适应二值化。使用方法是在 cv::threshold 函数中加入 THRESH_OTSU 标志。

3.1 Otsu 示例代码

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main() {
    Mat gray = imread("E:/image/lena.png", IMREAD_GRAYSCALE);
    if (gray.empty()) {
        cerr << "图像加载失败!" << endl;
        return -1;
    }

    Mat binary;
    // thresh 参数可以设为 0,Otsu 算法会自动计算最佳阈值
    double otsu_thresh_val = threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
    cout << "Otsu 自动选择的阈值为:" << otsu_thresh_val << endl;

    imshow("原始灰度图像", gray);
    imshow("Otsu 二值化", binary);
    waitKey(0);
    return 0;
}

Otsu二值化

4. 三角二值化(Triangle Thresholding)

三角二值化(Triangle Thresholding)是一种基于图像直方图分析的方法,适用于单峰或近似单峰直方图的情况。它使用直方图的形状特征来确定一个合适的阈值。该方法通常用于光照均匀、前景与背景灰度分布明显的图像。不适用于双峰或多峰直方图(例如 Otsu 方法更适用于双峰直方图)

4.1 三角二值化原理

  • 计算图像灰度直方图。
  • 选择直方图中的最大峰值点作为基准点。
  • 计算从直方图起始点到峰值点之间的最大距离来确定阈值。

4.2 三角二值化示例代码

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main() {
    // 读取灰度图像
    Mat gray = imread("lena.png", IMREAD_GRAYSCALE);
    if (gray.empty()) {
        cerr << "图像加载失败!" << endl;
        return -1;
    }
    
    Mat binary;
    // 使用 Triangle 方法自动计算阈值
    double triangle_thresh_val = threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_TRIANGLE);
    cout << "三角阈值计算结果:" << triangle_thresh_val << endl;
    
    imshow("原始灰度图像", gray);
    imshow("Triangle 二值化", binary);
    waitKey(0);
    return 0;
}

三角二值化

5. 自适应阈值二值化

在光照不均匀的场景下,全局阈值方法可能效果不佳,此时自适应阈值二值化更为有效。OpenCV 提供了 cv::adaptiveThreshold 函数,根据局部邻域信息动态确定阈值。

5.1 cv::adaptiveThreshold 函数

函数原型如下:

void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue,
                       int adaptiveMethod, int thresholdType, int blockSize, double C);
  • src:输入灰度图像。
  • dst:输出二值图像。
  • maxValue:二值化后像素的最大值(通常为 255)。
  • adaptiveMethod:自适应方法,如 ADAPTIVE_THRESH_MEAN_C(邻域均值)或 ADAPTIVE_THRESH_GAUSSIAN_C(高斯加权)。
  • thresholdType:阈值类型(通常为 THRESH_BINARY)。
  • blockSize:用于计算局部阈值的邻域大小(必须为奇数)。
  • C:从计算出的平均值中减去的常数,起到微调作用。

5.2 自适应阈值示例代码

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main() {
    Mat gray = imread("E:/image/lena.png", IMREAD_GRAYSCALE);
    if (gray.empty()) {
        cerr << "图像加载失败!" << endl;
        return -1;
    }

    Mat adaptive_binary;
    // 使用自适应阈值,将邻域均值作为局部阈值,blockSize 为 11,C 为 2
    adaptiveThreshold(gray, adaptive_binary, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 11, 2);

    imshow("原始灰度图像", gray);
    imshow("自适应阈值二值化", adaptive_binary);
    waitKey(0);
    return 0;
}

自适应阈值方法通过考虑局部信息,使得在光照不均时也能得到较好的二值化结果,可以看到更多的细节
在这里插入图片描述

6. 应用场景与小结

图像二值化是图像预处理的重要步骤,全局阈值、Otsu 自动阈值和自适应阈值各有适用场景。

  • 全局阈值:简单、快速,适用于光照均匀的图像;
  • Otsu 方法:自动计算最佳阈值,适用于双峰直方图;
  • 自适应阈值:针对局部光照不均效果较好。

通过选择合适的方法和参数,可以有效分离图像中的前景与背景,为后续的图像处理和分析任务打下良好基础。

主要应用场景:

  • 文档处理:二值化能将文档转换为黑白图像,有助于 OCR 识别。
  • 目标分割:二值化用于将前景与背景分离,便于后续的物体检测和形态学处理。
  • 图像分析:二值化简化了图像信息,适合形状分析和轮廓提取。

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

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

相关文章

通过Appium理解MCP架构

MCP即Model Context Protocol&#xff08;模型上下文协议&#xff09;&#xff0c;是由Anthropic公司于2024年11月26日推出的开放标准框架&#xff0c;旨在为大型语言模型与外部数据源、工具及系统建立标准化交互协议&#xff0c;以打破AI与数据之间的连接壁垒。 MCP架构与Appi…

分享一个Pyside6实现web数据展示界面的效果图

今天又是有问题直接找DS的一天&#xff0c;每日一问&#xff0c;今天我的问题是“怎么将pyside6生成的界面转成web界面&#xff0c;使用python语言实现web界面”&#xff0c;等了一会&#xff0c;DS给我提供了两种方案&#xff0c;方案如下&#xff1a; 然后&#xff0c;让我们…

FALL靶场通关攻略

1&#xff0c;下载好靶机后打开&#xff0c;通过kali扫描靶机ip和端口&#xff0c;得到靶机ip为192.168.50.144 2&#xff0c;扫描目录 3&#xff0c;访问靶机 4&#xff0c;访问扫描到的test.php,得到缺少GET请求参数的提示 5&#xff0c;使用FUZZ来扫出参数为file 6&#xff…

Mybatis日志模块分析--适配器模式+代理模式

适配器模式 日志在我们开发过程中占据了一个非常重要的地位&#xff0c;是开发和运维管理之间的桥梁&#xff0c;在Java中的日志框架也非常多&#xff0c;Log4j,Log4j2,Apache Commons Log,java.util.logging,slf4j等&#xff0c;这些工具对外的接口也都不尽相同&#xff0c;为…

圆球法线图,图生法线图 图片生成法线图

目录 圆球法线图 根据图片生成法线图 深度图计算法线图 圆球法线图 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D# 定义球体的参数 radius 1.0 resolution 100# 生成球体表面的点 u np.linspace(0, 2 * np.pi, resoluti…

Java基于SpringBoot的网络云端日记本系统,附源码+文档说明

博主介绍&#xff1a;✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&…

【自用记录】本地关联GitHub以及遇到的问题

最近终于又想起GitHub&#xff0c;想上传代码和项目到仓库里。 由于很早之前有在本地连接过GitHub&#xff08;但没怎么用&#xff09;&#xff0c;现在需要重新搞起&#xff08;操作忘得差不多&#xff09;。 在看教程实操的过程中遇到了一些小问题&#xff0c;遂记录一下。 前…

页码设置相关问题记录

Q&#xff1a;中间没有显示页码怎么办&#xff1f; A&#xff1a;“页眉和页脚”-“页码”-“页面底端”-“普通数字2” Q&#xff1a;想让页码在某几节连续怎么办&#xff1f; A&#xff1a; ① 先保证节与节之间插入了“分节符”&#xff08;如何插入分节符和如何显示分节符…

什么是数据集市

数据集市&#xff08;Data Mart&#xff09;是数据管理领域的核心概念&#xff0c;其定义为面向特定业务领域或用户群体的小型数据仓库子集&#xff0c;专注于部门级业务分析&#xff0c;具有快速响应、灵活部署等特点。以下从定义、特点、类型、结构、应用场景及与其他数据架构…

【HC-05蓝牙模块】主要性能指标与通信基础知识

一、HC-05 基础学习视频 HC-05蓝牙串口通信模块调试与应用1 二、HC-05学习视频课件

如何缩短研发周期,降低研发成本?全星APQP软件为您提供解决方案

如何缩短研发周期&#xff0c;降低研发成本&#xff1f;全星APQP软件为您提供解决方案 一、 系统概述 全星研发管理APQP软件系统是一款专为产品研发和质量管控打造的智能化平台&#xff0c;旨在帮助企业高效推进APQP&#xff08;先期产品质量策划&#xff09;流程&#xff0c…

Github Webhook 以及主动式

Github配置 GitHub 默认支持两种 Content-Type: application/json application/x-www-form-urlencoded 特别要注意 Content-Type 我们选择: application/json Flask代码 import os import shutil import subprocess from flask import Flask, request, jsonifyapp = Fla…

猜猜我用的是哪个大模型?我的世界游戏界面简单的模拟效果

我的罗里吧嗦的&#xff0c;根据小朋友的要求&#xff0c;边听边写边输入的提示词&#xff1a; 请生成一段完整的在网页中用html5和javascript代码模拟“我的世界”中游戏场景的互动画面&#xff0c;要求提供若干人物选项可以选择&#xff0c;请自行选择需要使用哪些库或框架来…

基于龙芯3A5000处理器,全国产标准6U VPX板卡解决方案

1&#xff0c;产品功能 本产品为一款高可靠性的基于龙芯3A5000处理器以及 7A2000芯片组的标准6U VPX板卡&#xff0c;具有以太网、SATA、PCIE&#xff0c;以及显示等接口&#xff0c;产品功能框图如图1所示&#xff1a; 图1 系统框图 2&#xff0c;技术指标 序号 项目 指标…

Unity编辑器功能及拓展(3) —[Attribute]特性

在 Unity 中&#xff0c;[Attribute]格式的特性是用于扩展编辑器功能、控制序列化行为和调整 Inspector 显示,进行编辑器拓展的核心工具。 一.基础编辑器拓展 1.基础序列化控制 1.[SerializeField] 强制显示私有变量到Inspector 2.[HideInInspector] 隐藏该字段在Inspect…

HarmonyOS NEXT——鸿蒙神策埋点(二)

在上一章我分享了鸿蒙客户端集成神策埋点sdk的过程&#xff0c;现在我们需要服务端的小伙伴配置集成服务端sdk接收处理数据信息&#xff0c;以下是集成的过程。 Java服务端sdk集成 1、获取神策数据平台url地址 1、导入集成&#xff1a; dependencies {compile com.sensorsda…

编程考古-Borland JBuilder:一场关于Java灵魂的战争与救赎

本文也是填之前一位网友让谈谈JBuilder的一个坑&#xff0c;感谢各位技术爱好者的支持。感谢关注小编&#xff0c;你的关注&#xff0c;是我更新的动力。 本篇章节如下&#xff1a; 序章&#xff1a;JBuilder的黄金时代 Borland的JBuilder&#xff1a;纯技术主义的胜利 生死…

【day4】数据结构刷题 树

6-1 二叉树的遍历 函数接口定义&#xff1a; void InorderTraversal( BinTree BT ); void PreorderTraversal( BinTree BT ); void PostorderTraversal( BinTree BT ); void LevelorderTraversal( BinTree BT ); 其中BinTree结构定义如下&#xff1a; typedef struct TNode *Po…

Elea AI:以人工智能之力推动病理实验室革新的技术突破与实践探索

Elea AI:以人工智能之力推动病理实验室革新的技术分析 一、病理实验室现状与 Elea AI 的革新契机 (一)传统病理实验室的痛点剖析 在医疗体系中,病理实验室扮演着至关重要的角色,其诊断结果是疾病确诊与后续治疗方案制定的关键依据。然而,当前传统病理实验室在实际运作过…

相似度计算 ccf-csp 2024-2-2

#include<bits/stdc.h> using namespace std;int main() {// 定义两个变量 n 和 m&#xff0c;分别用于存储两篇文章的单词个数int n, m;// 从标准输入读取 n 和 m 的值cin >> n >> m;// 定义三个 map 容器&#xff0c;A 用于存储并集&#xff0c;T 用于标记…