OpenCV 分水岭算法过分割:基于种子标记的图像分割
以下是使用 OpenCV 4.0 库实现基于种子标记的分水岭算法(cv::watershed)对输入图像进行过分割的 C++ 代码示例:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
// 生成随机种子点
void generateSeedPoints(Mat& img, int K, std::vector<Point>& seedPoints) {
int M = img.rows;
int N = img.cols;
float minDistance = sqrtf(M * N / K) * 0.5;
std::vector<cv::Point2f> diskSamples;
cv::theRNG().state = cv::getTickCount(); // 设置随机数种子
cv::theRNG().run( cv::Mat(K, 1, CV_32FC2), diskSamples, true ); // 泊松磁盘采样
for (const auto& sample : diskSamples) {
cv::Point seedPoint(sample.x * minDistance + N / 2, sample.y * minDistance + M / 2);
seedPoints.push_back(seedPoint);
}
}
int main() {
// 读取彩色图像
Mat img = imread("input_image.jpg");
if (img.empty()) {
std::cout << "Failed to read image!" << std::endl;
return -1;
}
int K = 1000;
std::vector<Point> seedPoints;
generateSeedPoints(img, K, seedPoints);
// 创建种子标记图像并初始化为-1
Mat markers = Mat::zeros(img.size(), CV_32S);
for (int i = 0; i < K; ++i) {
markers.at<int>(seedPoints[i]) = i + 1;
}
// 分水岭算法
watershed(img, markers);
// 可视化结果
Mat result = Mat::zeros(img.size(), img.type());
for (int i = 0; i < img.rows; ++i) {
for (int j = 0; j < img.cols; ++j) {
if (markers.at<int>(i, j) == -1) {
result.at<Vec3b>(i, j) = img.at<Vec3b>(i, j);
} else {
result.at<Vec3b>(i, j) = Vec3b(255, 255, 255); // 标记为种子点的位置
}
}
}
// 显示结果
imshow("Result", result);
waitKey(0);
return 0;
}
说明:
- 代码首先读取输入图像,并根据用户指定的参数 K 生成 K 个随机种子点。
- 生成种子点的函数
generateSeedPoints使用泊松圆盘采样方法,确保点间距离大于 (M * N / K)0.5。 - 然后,代码创建了一个标记图像,并在种子点的位置进行标记。
- 最后,代码使用 OpenCV 的
watershed函数进行分水岭算法,并将结果可视化。
注意:
- 确保将输入图像命名为 "input_image.jpg" 并放置在与代码文件相同的目录中。
- 代码的运行时间取决于图像的大小和计算机性能。
- 此代码仅为示例,您可以根据需要进行修改和优化。
原文地址: https://www.cveoy.top/t/topic/bnho 著作权归作者所有。请勿转载和采集!