图像二值化(Binarization)是将图像转换为只有两种颜色(通常是黑和白)的过程。它是图像预处理中的常见操作,尤其是在图像分割、边缘检测和特征提取等任务中,二值化可以帮助简化图像,使得后续的处理变得更为高效。
在 OpenCV 中,图像二值化常用的函数有 cv::threshold()
和 cv::adaptiveThreshold()
。这些函数可以将灰度图像转换为二值图像,通过设置不同的阈值(threshold),将像素值大于阈值的部分设为白色,小于阈值的部分设为黑色。
cv::threshold()
cv::threshold()
是 OpenCV 中最常用的二值化函数,用于将图像的像素值与给定的阈值进行比较,进而转换为二值图像。
函数原型:
double cv::threshold(
cv::InputArray src, // 输入图像,通常是灰度图像
cv::OutputArray dst, // 输出图像,二值化后的图像
double thresh, // 阈值
double maxValue, // 最大值,通常设为 255
int thresholdType // 阈值类型,决定了二值化的方式
);
src
:输入图像,必须是单通道(灰度)图像,通常类型为 CV_8U
(无符号8位整数)。dst
:输出图像,二值化后的图像,类型与输入图像相同。thresh
:阈值,所有大于该值的像素将设置为 maxValue
(通常为 255),否则设置为 0。maxValue
:大于阈值的像素值将被设置为此值(通常为 255,表示白色)。thresholdType
:二值化类型,决定了如何将像素值与阈值进行比较,常用的阈值类型有:
cv::THRESH_BINARY
:如果像素值大于阈值,则设置为 maxValue
,否则设置为 0。cv::THRESH_BINARY_INV
:如果像素值小于阈值,则设置为 maxValue
,否则设置为 0。cv::THRESH_TRUNC
:如果像素值大于阈值,则将其截断为阈值。cv::THRESH_TOZERO
:如果像素值大于阈值,则保持原值,否则设置为 0。cv::THRESH_TOZERO_INV
:如果像素值小于阈值,则保持原值,否则设置为 0。threshold
返回一个double
,表示实际使用的阈值,通常这个值和 thresh
相同。
#include
#include
int main() {
// 读取灰度图像
cv::Mat img = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
if (img.empty()) {
std::cerr << "Failed to load image!" << std::endl;
return -1;
}
// 创建输出图像
cv::Mat binaryImg;
// 使用 cv::threshold 进行二值化
double thresh = 128; // 选择阈值 128
double maxValue = 255;
cv::threshold(img, binaryImg, thresh, maxValue, cv::THRESH_BINARY);
// 显示结果
cv::imshow("Original Image", img);
cv::imshow("Binary Image", binaryImg);
cv::waitKey(0);
return 0;
}
cv::adaptiveThreshold()
在某些情况下,图像的亮度可能存在不均匀的情况(例如,图像不同部分的光照不同)。在这种情况下,固定阈值可能无法有效地分割图像。自适应阈值(Adaptive Thresholding)是应对这一问题的好方法,它会根据图像局部区域的像素值动态调整阈值。
void cv::adaptiveThreshold(
cv::InputArray src, // 输入图像,必须是灰度图像
cv::OutputArray dst, // 输出图像,二值化后的图像
double maxValue, // 最大值
int adaptiveMethod, // 自适应方法,详见下面的参数表
int thresholdType, // 二值化类型,同上
int blockSize, // 邻域大小,定义计算阈值的区域大小,必须是奇数
double C // 常数,调整阈值的值(减去常数来避免阈值过高)
);
src
:输入图像,必须是单通道的灰度图像。dst
:输出图像,二值化后的图像。maxValue
:大于局部阈值的像素值将设置为此值(通常为 255)。adaptiveMethod
:自适应方法:
cv::ADAPTIVE_THRESH_MEAN_C
:计算邻域区域的均值,并作为阈值。cv::ADAPTIVE_THRESH_GAUSSIAN_C
:计算邻域区域的**加权均值(使用高斯权重)**作为阈值。thresholdType
:二值化类型,通常使用 cv::THRESH_BINARY
或 cv::THRESH_BINARY_INV
。blockSize
:邻域区域的大小,必须是奇数(例如 3, 5, 7 等)。C
:偏移值调整常数,计算出的阈值减去C即为最终结果。这个常数值通常设置为正数,来避免过高的阈值。#include
#include
int main() {
// 读取灰度图像
cv::Mat img = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
if (img.empty()) {
std::cerr << "Failed to load image!" << std::endl;
return -1;
}
// 创建输出图像
cv::Mat adaptiveBinaryImg;
// 使用自适应阈值进行二值化
double maxValue = 255;
int adaptiveMethod = cv::ADAPTIVE_THRESH_MEAN_C;
int thresholdType = cv::THRESH_BINARY;
int blockSize = 11; // 邻域大小
double C = 2; // 偏移值调整量
cv::adaptiveThreshold(img,
adaptiveBinaryImg,
maxValue,
adaptiveMethod,
thresholdType,
blockSize,
C);
// 显示结果
cv::imshow("Original Image", img);
cv::imshow("Adaptive Binary Image", adaptiveBinaryImg);
cv::waitKey(0);
return 0;
}
在这个例子中:
cv::adaptiveThreshold()
使用了自适应均值法 cv::ADAPTIVE_THRESH_MEAN_C
,并且设置了一个邻域大小为 11 的区域来计算每个像素的阈值。C
用于从计算出来的均值中减去一个常数,调整二值化效果。Otsu方法,也叫最大类间方差法或者大津法(由大津展之(英语:Nobuyuki Otsu)提出),是一种自动计算最优阈值的方法,它可以在全局范围内通过最大化类间方差来选择最佳的分割阈值。
cv::Mat img = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat binaryImg;
cv::threshold(img, binaryImg, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU);