OpenCV分水岭算法

#include<iostream>
#include <opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/video/tracking.hpp>
using namespace std;
using namespace cv;



/*
任务:

选择一副彩色图像,对其中前景进行初步分割(可采用任何合适的分割方式,
例如利用阈值或利用颜色信息等等,得到二值图,其中前景用白色表示,背景用黑色表示),
然后利用形态学运算得到标记图(前景、背景、不确定区域各1种标记,不确定区域标记为0),
最后利用分水岭分割算法进行分割,要求显示出原彩色图、初步分割结果(二值图)、标记图、
3种最终分割结果(边缘图、区域图、区域图与原图混合结果)
*/
class WatershedSegmenter {
private:
	cv::Mat markers; // 标记图(既是输入,也是结果)
public:
	// 设置标记图
	void setMarkers(const cv::Mat& markerImage) {
		// 转换成整数型图像
		markerImage.convertTo(markers, CV_32S);
	}
	// 应用分水岭分割
	cv::Mat process(const cv::Mat& image) {
		cv::watershed(image, markers);
		return markers.clone();
	}
	// 以图像的形式返回分割结果
	cv::Mat getSegmentation() {
		cv::Mat tmp;
		// 所有标签值大于255的区域都赋值为255
		// 标签值小于0的赋为0
		markers.convertTo(tmp, CV_8U);

		return tmp;
	}
	// 以图像的形式返回分水岭
	cv::Mat getWatersheds() {
		//cv::Mat tmp;
		// 在转换时将每个像素p转换为255p+255
		//markers.convertTo(tmp, CV_8U, 255, 255);

		return markers > -1;
	}
};


void main()
{
	Mat image;
	image = cv::imread("1.jpg");
	if (image.empty())
	{
		cout << "读取图像失败" << endl;
		exit(EXIT_FAILURE);
	}
	cv::imshow("Origional Image", image);
	cv::Mat binary = cv::imread("bin.bmp", cv::IMREAD_GRAYSCALE);
	if (binary.empty())
	{
		cout << "读取图像失败" << endl;
		exit(EXIT_FAILURE);
	}
	cv::imshow("初步分割结果(二值图)", binary);
	cv::Mat fg;
	// 用默认结构元素腐蚀4次
	cv::erode(binary, fg, cv::Mat(), cv::Point(-1, -1), 4);

	// 标识不含物体的图像像素
	cv::Mat bg;
	// 用默认结构元素膨胀4次
	cv::dilate(binary, bg, cv::Mat(), cv::Point(-1, -1), 4);
	// 将背景像素设为128,阈值1-254区间均可
	cv::threshold(bg, bg, 1, 128, cv::THRESH_BINARY_INV);
	// 通过合并之前两幅图得到标记图像
	// (前景为255,背景为128,待定为0)
	cv::Mat markers = fg + bg;
	cv::imshow("标记图", markers);
	// 创建分水岭分割类的对象
	WatershedSegmenter segmenter;
	// 设置标记图像,然后执行分割过程
	segmenter.setMarkers(markers);
	segmenter.process(image);
	cv::imshow("分割结果(边缘图)", segmenter.getWatersheds());
	// 得到方便观察的分割结果(边缘像素为黑色)
	cv::Mat resultForShow = segmenter.getSegmentation();
	cv::imshow("分割结果(区域图)", resultForShow);
	// 将分割结果与原图融合,以便于观察结果的正确性
	cv::cvtColor(resultForShow, resultForShow, cv::COLOR_GRAY2BGR);
	resultForShow = resultForShow * 0.5 + image * 0.5;
	cv::imshow("分割结果", resultForShow);
	int c = waitKey(0);
	if (c == 27)
	{
		exit;
	}
	destroyAllWindows();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV分水岭算法是一种常用的图像分割算法,可以有效地将图像中的目标从背景中分离出来。该算法基于分水岭的概念,通过将图像视为地形图,将图像中的边缘和局部极值点作为水域,然后根据水流的规则,将图像分割为不同的区域。 在OpenCV中,使用分水岭算法进行图像分割需要经过以下几个步骤: 1. 预处理:首先,对图像进行预处理,包括灰度化、平滑处理和二值化等操作,以便更好地分离目标和背景。 2. 标记:通过手动或自动方式,标记图像中的前景和背景区域。通常情况下,前景区域是我们感兴趣的目标,而背景区域是我们想要分离的部分。 3. 距离变换:基于标记的结果,计算图像中每个像素点到最近标记点的距离,这将被用于下一步计算分水岭线。 4. 分水岭转换:根据距离变换结果,计算分水岭线,将图像划分为不同的区域。这些区域将成为我们的分割结果。 5. 后处理:根据实际需求,对分割结果进行后处理,如去除小区域、连接相邻区域等。 通过这些步骤,OpenCV分水岭算法能够对图像进行准确的分割,将目标从背景中分离出来,为后续的图像处理和分析提供基础。 引用提供了关于OpenCV分水岭算法的详细介绍和应用案例,可以参考该文献获取更多相关信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [OpenCV——分水岭算法](https://blog.csdn.net/qq_36686437/article/details/131357062)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [分水岭算法(Watershed algorithm)与OpenCV实现](https://blog.csdn.net/qingyafan/article/details/44260817)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值