Opencv c++代码实现分水岭分割算法,并将其用于下面图像分割,其算法:(1)先使用 Otsu's 二值化对图像进行二值化 (2)使用开运算去除图像中的细小白色噪点 (3)通过距离变换来确定前景图像 (4)可以看到硬币的中心像素值最大(中心离背景像素最远)。对其进行二值处理就得到了分离的前景图。 (5)通过膨胀运算,使得一部分背景成为了物体到的边界,得到的图像中的黑色区域肯定是真实背景。 (6)使用膨胀图减去前景图,得到不确定区域,这部分区域不确定是硬币还是背景,这些区域通常在前景和背景接触的区域(或者两个不同硬币接触的区域),称之为边界。通过分水岭算法应该能找到确定的边界。 (7)现在可以确定哪些是硬币区域,哪些是背景区域。然后需要创建标记(marker,它是一个与原始图像大小相同的矩阵,int32数据类型),表示其中的每个区域。分水岭算法将标记的0的区域视为不确定区域,将标记为1的区域视为背景区域,将标记大于1的正整数表示我们想得到的前景。 (8)可以使用 connectedComponents() 来实现这个功能,它是用0标记图像的背景,用大于0的整数标记其他对象。但是OpenCV的分水岭分割函数,会用0表示不确定区域,所以需要对标记统一加一,然后将上一步计算的不确定区域部分标记为0. (9)现在可以调用watershed函数分割图像,如下: watershed(src, markers); (10)maker中标记为-1的地方就是分界线,makers中的最大值减1就是统计的个数。
时间: 2024-02-22 20:00:35 浏览: 199
以下是 Opencv c++ 代码实现分水岭分割算法,实现对图像的分割:
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat img = imread("coins.jpg", IMREAD_GRAYSCALE);
if (img.empty())
{
cout << "Could not read the image!" << endl;
return -1;
}
// Otsu's 二值化
Mat binary;
threshold(img, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
// 开运算去除细小白色噪点
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
morphologyEx(binary, binary, MORPH_OPEN, kernel);
// 距离变换
Mat dist;
distanceTransform(binary, dist, DIST_L2, 3);
// 取硬币中心像素值最大的区域作为前景图像
normalize(dist, dist, 0, 1, NORM_MINMAX);
threshold(dist, dist, 0.5, 1.0, THRESH_BINARY);
// 膨胀运算
Mat kernel2 = getStructuringElement(MORPH_ELLIPSE, Size(9, 9));
dilate(dist, dist, kernel2);
// 计算不确定区域
Mat sure_bg;
threshold(dist, sure_bg, 0.5, 1.0, THRESH_BINARY_INV);
Mat sure_fg;
threshold(dist, sure_fg, 0.5, 1.0, THRESH_BINARY);
// 不确定区域
Mat uncertain;
Mat uncertain_temp;
subtract(sure_bg, binary, uncertain_temp);
subtract(uncertain_temp, sure_fg, uncertain);
// 创建标记
Mat marker(binary.size(), CV_32S);
marker.setTo(0);
marker.setTo(1, sure_bg);
marker.setTo(2, uncertain);
marker.setTo(3, sure_fg);
// 分水岭算法
watershed(img, marker);
// 统计硬币个数
int coin_count = 0;
for (int i = 0; i < marker.rows; i++)
{
for (int j = 0; j < marker.cols; j++)
{
if (marker.at<int>(i, j) == -1)
{
coin_count++;
}
}
}
cout << "The number of coins is: " << coin_count << endl;
// 显示结果
Mat result;
convertScaleAbs(marker, result);
imshow("Result", result);
waitKey(0);
return 0;
}
```
这个程序实现了对硬币图像的分割,并统计了硬币的个数。
阅读全文