IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> cv::watershed(imgmask) -> 正文阅读

[游戏开发]cv::watershed(imgmask)

如标题,又说回分水岭。

分水岭的源码分析可参考OpenCV 源码中分水岭算法 watershed 函数源码注解_Endless_91的博客-CSDN博客_watershed源码这个博主。

然后我写了下流程:

?而对于我的应用,不是彩图,是二值图,所以只能如下去构造。

connectedComponents(peak_image, imglabels);
	imglabels.convertTo(imglabels, CV_32SC1);
	///分水岭分割
	vector<Mat> resultmats;
	Mat binary_8UC3;
	resultmats.push_back(realsingleimg);
	resultmats.push_back(realsingleimg);
	resultmats.push_back(realsingleimg);
	merge(resultmats,binary_8UC3);
	Mat unknown;//得到未知区域 即分界线的划分涉及区域
	bitwise_xor(realsingleimg,peak_image,unknown);

	imglabels.forEach<int>(
		[&unknown](int &pixel, const int *position) -> void
		{
			pixel+=100;
			if((unknown.ptr<uchar>(position[0])[position[1]])>0)
			{
				pixel=0;
			}
		}
	);
	watershed(binary_8UC3, imglabels);///分水岭分割结束

这样的后果就是过分割严重,想着用下面的轴相似来抑制极大值。但是鲁棒性并没有我之前传的那一版本好。

/*
 *float mergedistanceth:每两个中心点 每个轴之间的距离差阈值,小于此阈值则是相似轴。越小相似轴越少,则合并的点越少
 *float similarratio:相似轴占所有轴的比例,大于此阈值则合并。越小合并的点越多。
 * */
void peakNMSuppress(Mat objbw,vector<Point> origipeaks,float mergedistanceth,float similarratio,vector<Point> &mergepeaks)
{
	int origipeaksnum=origipeaks.size();

	vector<PEAKINFO> peaksaxises;
	for(int ptid=0;ptid!=origipeaksnum;ptid++)
	{
		PEAKINFO tmppeakinfo;
		tmppeakinfo.peak=origipeaks[ptid];
		tmppeakinfo.proceeded=0;

		//得到每个peak的四个轴
		getAxisLengths(objbw,origipeaks[ptid],tmppeakinfo.axises);
		peaksaxises.push_back(tmppeakinfo);
	}

	//对每个点的特征进行判断,极度相似的才是需要合并的
	for(int peakid=0;peakid!=peaksaxises.size();peakid++)
	{
		if(peaksaxises[peakid].proceeded)
			continue;

		Vec4b currentpeakinfo=peaksaxises[peakid].axises;

		vector<Point> tmpmerged;
		tmpmerged.push_back(peaksaxises[peakid].peak);
		peaksaxises[peakid].proceeded=1;

		for(int compareid=peakid+1;compareid!=peaksaxises.size();compareid++)
		{
			if(peaksaxises[compareid].proceeded)
				continue;

			Vec4b comparepeakinfo=peaksaxises[compareid].axises;
			float similarcount=0.0f;
			for(int id=0;id!=4;id++)
			{
				float similardegree=abs(currentpeakinfo.val[id]-comparepeakinfo.val[id]);
				if(similardegree<mergedistanceth)
				{
					similarcount += 1;
				}
			}
			similarcount /= 4;//表示极度相似的轴的比例
			if(similarcount>=similarratio)
			{
				peaksaxises[compareid].proceeded=1;
				tmpmerged.push_back(peaksaxises[compareid].peak);
			}
		}

		int similarpeaksnum=tmpmerged.size();
		if(similarpeaksnum==1)
		{
			mergepeaks.push_back(tmpmerged[0]);
		}
		else
		{
			//merge many peak points...
			float xsum=tmpmerged[0].x,ysum=tmpmerged[0].y;
			for(int pid=1;pid!=similarpeaksnum;pid++)
			{
				xsum += tmpmerged[pid].x;
				ysum += tmpmerged[pid].x;
			}
			Point mergedpeak(xsum/similarpeaksnum,ysum/similarpeaksnum);
			mergepeaks.push_back(mergedpeak);
		}
	}

}

//得到每个peak的四个轴
void getAxisLengths(Mat objbw,Point peakpt,Vec4w &axislengths)
{
	int rows=objbw.rows;
	int cols=objbw.cols;

	//0 degree...水平
	axislengths.val[0]=1;
	int r=peakpt.y;
	//left...
	for(int c=peakpt.x-1;c>-1;c--)
	{
		if(objbw.ptr<uchar>(r)[c]!=0)
		{
			(axislengths.val[0])++;
		}
		else
			break;
	}
	//right...
	for(int c=peakpt.x+1;c!=cols;c++)
	{
		if(objbw.ptr<uchar>(r)[c]!=0)
		{
			(axislengths.val[0])++;
		}
		else
			break;
	}

	//90 degree...垂直
	axislengths.val[1]=1;
	int c=peakpt.x;
	//up...
	for(r=peakpt.y-1;r>-1;r--)
	{
		if(objbw.ptr<uchar>(r)[c]!=0)
		{
			(axislengths.val[1])++;
		}
		else
			break;
	}
	//bottom...
	for(r=peakpt.y+1;r!=rows;r++)
	{
		if(objbw.ptr<uchar>(r)[c]!=0)
		{
			(axislengths.val[1])++;
		}
		else
			break;
	}

	//45 degree...
	axislengths.val[2]=1;
	c=peakpt.x;
	r=peakpt.y;
	//up...
	for(r=peakpt.y-1;r>-1;r--)
	{
		for(c=peakpt.x+1;c!=cols;c++)
		{
			if(objbw.ptr<uchar>(r)[c]!=0)
			{
				(axislengths.val[2])++;
			}
			else
				break;
		}
	}
	c=peakpt.x;
	r=peakpt.y;
	//down...
	for(r=peakpt.y+1;r!=rows;r++)
	{
		for(c=peakpt.x-1;c>-1;c--)
		{
			if(objbw.ptr<uchar>(r)[c]!=0)
			{
				(axislengths.val[2])++;
			}
			else
				break;
		}
	}

	//135 degree...
	axislengths.val[3]=1;
	c=peakpt.x;
	r=peakpt.y;
	//up...
	for(r=peakpt.y-1;r>-1;r--)
	{
		for(c=peakpt.x-1;c>-1;c--)
		{
			if(objbw.ptr<uchar>(r)[c]!=0)
			{
				(axislengths.val[3])++;
			}
			else
				break;
		}
	}
	c=peakpt.x;
	r=peakpt.y;
	//down...
	for(r=peakpt.y+1;r!=rows;r++)
	{
		for(c=peakpt.x+1;c!=cols;c++)
		{
			if(objbw.ptr<uchar>(r)[c]!=0)
			{
				(axislengths.val[3])++;
			}
			else
				break;
		}
	}
}

还是没有链接里的效果好。?

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-07 23:02:30  更:2022-04-07 23:02:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/16 21:08:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码