•当物体和背景像素的灰度分布十分明显时,可以用适用于整个图像的单个 (全局)阈值处理,其算法如下: 为全局阈值T选择一个初始估计值 用单个阈值T分割图像。将产生两组像素:G,和G2,其中G1由灰度值大 于T的所有像素组成,Gz由所有小于等于T的像素组成 对Gi和Gz的像素分别计算平均灰度值(均值)mi和m2 计算一个新的阈值:T = (mi + mz) 重复步骤(2)到步骤(4),直到连续迭代中的两个T值小于预定义的 AT为止。
如果您觉得有用,不妨打赏和采纳该评论,希望能对您有所帮助
使用cv::thresold的写法:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
// 读取图像
Mat img = imread("image.png", IMREAD_GRAYSCALE);
// 选择一个初始阈值T
double T = 127;
// 定义一个预设的AT
double AT = 1;
// 定义一个循环标志
bool flag = true;
while (flag)
{
// 用单个阈值T分割图像
Mat thresh;
threshold(img, thresh, T, 255, THRESH_BINARY);
// 计算G1和G2的像素均值m1和m2
double m1 = mean(img, thresh)[0];
double m2 = mean(img, 255 - thresh)[0];
// 计算一个新的阈值T_new
double T_new = (m1 + m2) / 2;
// 判断T_new和T是否小于AT
if (abs(T_new - T) < AT)
{
// 结束循环
flag = false;
}
else
{
// 更新T为T_new
T = T_new;
}
}
// 显示分割后的图像
imshow("Thresholded Image", thresh);
waitKey(0);
destroyAllWindows();
}
不使用cv::thresold函数
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
// 读取图像
Mat img = imread("image.png", IMREAD_GRAYSCALE);
// 选择一个初始阈值T
double T = 127;
// 定义一个预设的AT
double AT = 1;
// 定义一个循环标志
bool flag = true;
while (flag)
{
// 定义两个像素组G1和G2
vector<uchar> G1, G2;
// 遍历图像中的每个像素
for (int i = 0; i < img.rows; i++)
{
for (int j = 0; j < img.cols; j++)
{
// 获取当前像素的灰度值
uchar pixel = img.at<uchar>(i, j);
// 根据阈值T将像素分到G1或G2中
if (pixel > T)
{
G1.push_back(pixel);
}
else
{
G2.push_back(pixel);
}
}
}
// 计算G1和G2的像素均值m1和m2
double m1 = mean(G1)[0];
double m2 = mean(G2)[0];
// 计算一个新的阈值T_new
double T_new = (m1 + m2) / 2;
// 判断T_new和T是否小于AT
if (abs(T_new - T) < AT)
{
// 结束循环
flag = false;
}
else
{
// 更新T为T_new
T = T_new;
}
}
// 创建一个输出图像
Mat dst = Mat::zeros(img.size(), img.type());
// 遍历图像中的每个像素
for (int i = 0; i < img.rows; i++)
{
for (int j = 0; j < img.cols; j++)
{
// 获取当前像素的灰度值
uchar pixel = img.at<uchar>(i, j);
// 根据阈值T将像素分为黑色或白色
if (pixel > T)
{
dst.at<uchar>(i, j) = 255;
}
else
{
dst.at<uchar>(i, j) = 0;
}
}
}
// 显示分割后的图像
imshow("Thresholded Image", dst);
waitKey(0);
destroyAllWindows();
}