OpenCv之图像二值化

目录

一、图像二值化的核心本质

[二、OpenCV 中二值化的核心方法](#二、OpenCV 中二值化的核心方法)

[2.1 固定阈值二值化(cv::threshold)](#2.1 固定阈值二值化(cv::threshold))

[2.2 自动最优固定阈值(Otsu / 三角法)](#2.2 自动最优固定阈值(Otsu / 三角法))

[2.3 自适应阈值二值化(cv::adaptiveThreshold)](#2.3 自适应阈值二值化(cv::adaptiveThreshold))

[三、 二值化测试代码和效果](#三、 二值化测试代码和效果)

[3.1 lean图测试三个算法](#3.1 lean图测试三个算法)

[3.2 以扫描文档处理为例](#3.2 以扫描文档处理为例)


一、图像二值化的核心本质

图像二值化是将灰度图像 (0~255)转换为纯黑白图像(仅 0 和 255 两个值)的过程,核心是通过「阈值」区分前景(目标)和背景:

  • 像素值 > 阈值 → 设为 255(白)
  • 像素值 ≤ 阈值 → 设为 0(黑)(或反向)

二值化是图像分割、轮廓检测、字符识别、缺陷检测 的基础,能大幅简化图像数据,突出目标区域。

二、OpenCV 中二值化的核心方法

OpenCV 提供两类二值化方法:固定阈值二值化 (手动设阈值)和自适应阈值二值化(自动算阈值),还有拓展的 Otsu / 三角法(自动找最优固定阈值)。

2.1 固定阈值二值化(cv::threshold)

cpp 复制代码
double threshold(
    InputArray src,       // 输入:单通道灰度图(必须!)
    OutputArray dst,      // 输出:二值化图像
    double thresh,        // 手动设定的阈值(0~255)
    double maxval,        // 超过阈值的像素赋值(通常255)
    int type              // 二值化类型
);

二值类型:

2.2 自动最优固定阈值(Otsu / 三角法)

核心原理: 无需手动设阈值,算法自动计算最优阈值 (最大化前景 / 背景分离度),只需在 type 后加 THRESH_OTSUTHRESH_TRIANGLE

  • THRESH_OTSU:适用于双峰直方图(前景和背景像素值分布明显分开);
  • THRESH_TRIANGLE:适用于单峰直方图(如医学图像、暗背景亮目标)。

2.3 自适应阈值二值化(cv::adaptiveThreshold)

核心原理: 针对光照不均 的图像(如阴影、渐变背景),为每个像素计算局部阈值 (以该像素为中心的邻域均值 / 高斯加权均值),能避免固定阈值的 "局部过曝 / 过暗" 问题。函数原型:

复制代码
void adaptiveThreshold(
    InputArray src,       // 输入:单通道灰度图
    OutputArray dst,      // 输出:二值化图像
    double maxValue,      // 最大值(通常255)
    int adaptiveMethod,   // 局部阈值计算方式
    int thresholdType,    // THRESH_BINARY/THRESH_BINARY_INV
    int blockSize,        // 邻域大小(奇数,如3、5、7、11)
    double C              // 常数:阈值 = 邻域均值 - C(调对比度)
);

关键参数

  • adaptiveMethod
    • ADAPTIVE_THRESH_MEAN_C:邻域算术均值作为阈值(速度快);
    • ADAPTIVE_THRESH_GAUSSIAN_C:邻域高斯加权均值作为阈值(效果更平滑);
  • blockSize:邻域越大,二值化越 "模糊";越小,越保留细节(需试 3/5/7/11);
  • C:减去的常数(正数→降低阈值,更多像素变白;负数→提高阈值,更多像素变黑)。

三、 二值化测试代码和效果

3.1 lean图测试三个算法

固定阈值 自动最优固定阈值和自适应阈值方法的二值化。

cpp 复制代码
void testBinaryImage()
{
	Mat GrayMat = imread(R"(D:\Study\OpenCvStudy\lean.jpg)", ImreadModes::IMREAD_GRAYSCALE);
	Mat Thresh_BinaryMat,Threah_BinaryInvMat,TruncMat,TozeoMat,TozeoInvMat;
	//阈值有效
	threshold(GrayMat, Thresh_BinaryMat, 125, 255, THRESH_BINARY);
	threshold(GrayMat, Threah_BinaryInvMat, 125, 255, THRESH_BINARY_INV);
	threshold(GrayMat, TruncMat, 125, 255, THRESH_TRUNC);
	threshold(GrayMat, TozeoMat, 125, 255, THRESH_TOZERO);
	threshold(GrayMat, TozeoInvMat, 125, 255, THRESH_TOZERO_INV);

	Mat Thresh_OTSU_Mat, Thresh_TRIANGLE_Mat;
	//两个算法自己取最优阈值 只支持灰度图
	threshold(GrayMat, Thresh_OTSU_Mat, 125, 255, THRESH_OTSU);
	threshold(GrayMat, Thresh_TRIANGLE_Mat, 125, 255, THRESH_TRIANGLE);
	//自适应法 均值法和高斯法
	Mat Thresh_Mean_Mat, Thresh_Gauss_Mat;
	adaptiveThreshold(GrayMat, Thresh_Mean_Mat,255, AdaptiveThresholdTypes::ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY,55,0);
	adaptiveThreshold(GrayMat, Thresh_Gauss_Mat, 255, AdaptiveThresholdTypes::ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 55, 0);

	imshow("GrayMat", GrayMat);
	imshow("Thresh_BinaryMat", Thresh_BinaryMat);
	imshow("Threah_BinaryInvMat", Threah_BinaryInvMat);
	imshow("TruncMat", TruncMat);
	imshow("TozeoMat", TozeoMat);
	imshow("TozeoInvMat", TozeoInvMat);
	imshow("Thresh_OTSU_Mat", Thresh_OTSU_Mat);
	imshow("Thresh_TRIANGLE_Mat", Thresh_TRIANGLE_Mat);
	waitKey();
}

3.2 以扫描文档处理为例

cpp 复制代码
int testBinaryImage2() {
	// 读取灰度图(必须单通道!)
	Mat img = imread(R"(D:\Study\OpenCvStudy\Test.jpg)", ImreadModes::IMREAD_GRAYSCALE);
	if (img.empty()) return -1;

	// 固定阈值二值化(白底黑字)
	Mat binary1;
	threshold(img, binary1, 127, 255, THRESH_BINARY); // 阈值127

	// 反向二值化(黑底白字)
	Mat binary2;
	threshold(img, binary2, 127, 255, THRESH_BINARY_INV);


	// Otsu 自动找阈值(thresh设0即可,函数返回最优值)
	Mat Otusbinary;
	double otsu_thresh = threshold(img, Otusbinary, 0, 255, THRESH_BINARY | THRESH_OTSU);
	cout << "Otsu 自动计算的最优阈值:" << otsu_thresh << endl;

	// 自适应阈值
	Mat binary_adaptive;
	adaptiveThreshold(
		img, binary_adaptive, 255,
		ADAPTIVE_THRESH_GAUSSIAN_C, // 高斯加权均值
		THRESH_BINARY_INV,          // 白底黑字
		11,                         // 邻域大小11×11
		2                           // 常数C=2
	);


	// 显示
	imshow("原图", img);
	imshow("THRESH_BINARY(白底黑字)", binary1);
	imshow("THRESH_BINARY_INV(黑底白字)", binary2);
	imshow("THRESH_OTSU(白底黑字)", Otusbinary);
	imshow("adaptiveThreshold(白底黑字)", binary_adaptive);
	waitKey(0);
	return 0;
}
相关推荐
云烟成雨TD12 小时前
Agent Scope Java 2.x 系列【4】模型层
java·人工智能·agent
dozenyaoyida12 小时前
AI与大模型新闻日报 | 2026-06-12
人工智能·ai·大模型·新闻
Blb12365412 小时前
技术解析-固体绝缘材料表面电阻率测试
人工智能·功能测试·制造·材料工程
云淡风轻~窗明几净13 小时前
角谷猜想的任意算法测试
数据结构·人工智能·算法
SaaS_Product13 小时前
同步盘操作教程:如何自动同步文件
人工智能·云计算·saas·onedrive
Z-D-K13 小时前
考验AI的“自我和意识“-AI对《红楼梦》后40回的改写(21)
人工智能·ai·aigc·交互·agi
CIO_Alliance13 小时前
API激增时代,如何用iPaaS实现API全生命周期治理
人工智能·ai·ipaas·系统集成·企业ai化转型
云烟成雨TD13 小时前
Agent Scope Java 2.x 系列【5】智能体抽象层
java·人工智能·agent
黎茗Dawn13 小时前
CNN、RNN与Self-Attention:定义、原理、复杂度与对比-AI轮回基本原理复习3
人工智能·rnn·cnn
Angelina_Jolie13 小时前
DiCLIP:用扩散模型激活CLIP的密集知识,弱监督语义分割新SOTA
人工智能