opencv中不稳定点集转换到稳定点集

这里只是一个项目的简要内容,

在机器视觉中,很多内容都会有不同程度的抖动和不确定性

特别是在实时检测到的物体上,在帧与帧之间通常差别不大也会有很大区别,这个主要是摄像头造成的

可以用二值化的方式查看,会发现处理后的图像边缘有闪烁,那就是摄像头产生的噪点


然后不要看噪点,对于需要边缘检测的可以试试,比如用canny,

噪点在实时canny的时候会产生变化的边缘长度,从而对检测造成影响


造成的影响可能是在实时检测的某一帧内就检测不到东西了,或者某几帧


这里假设采集到画面通过opencv处理后产生的是一组不稳定的点集,而你需要是一组稳定的点集

这里我用的方式是延迟,用多次判断来减少错误

当然有新的点需要更少的判断,而去掉一个点要多一些判断能有很好的效果,对于短时遮蔽和快速扰动有很好的忽略效果

stationPointArr是绘制用的点,也就是稳定的点集
stationPointTempArr是临时的点,也就是实时产生的点集

int stableValue1 = 0;//等大的稳定数字
int notStableValue1 = 0;//减少产生的不稳定数
int notStableValue2 = 0;//增加产生的不稳定数

//稳定数组里的点
if(stationPointArr.size() == 0)//如果稳定点数组不存在点,那么使用不稳定中的所有点
{
    stationPointArr = stationPointTempArr;
}else 
{	//进行稳定性判断
	//假设新旧点集等大 这里可能造成的问题就是消除一个的同时恢复成另一个会造成计算人为未改变
	if(stationPointArr.size()==stationPointTempArr.size())
	{
		if(stableValue1 >10)
		{//如果稳定数值超过10 则认为可以改变
			notStableValue1 = 0;
			notStableValue2 = 0;
			stableValue1 = 0;
		}
	}

	//假设旧点(用来绘制的点)集比临时的更大 用更长的时间来消除旧的点
	if(stationPointArr.size()>stationPointTempArr.size())
	{
		stableValue1 ++;

		if(notStableValue1<30)notStableValue1++;
		else 
		{
			notStableValue1 = 0;
			stationPointArr = stationPointTempArr;
		}
	}
	//假设新点集更大  用更短的时间来获取新的点
	if(stationPointArr.size()<stationPointTempArr.size())
	{
		stableValue1 ++;

		if(notStableValue2<10)notStableValue2++;
		else 
		{
			notStableValue2 = 0;
			stationPointArr = stationPointTempArr;
		}
	}
}


这里使用了交错判断方式,经过测试,可以发现遮蔽掉部分点,需要一段时间后才能看到点被去掉,而增加一些点可以快速增加,

快速遮蔽点然后撤回,会发现以前点没有影响




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 Welzl 算法来实现点集的最小包围球。以下是使用 OpenCV 和 C++ 实现的示例代码: ```c++ #include <opencv2/core.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <iostream> #include <vector> #include <random> using namespace cv; using namespace std; // 计算两个之间的距离 double dist(Point3d p1, Point3d p2) { return norm(p1 - p2); } // 判断 p 是否在圆心为 center,半径为 radius 的圆内 bool insideCircle(Point3d p, Point3d center, double radius) { return dist(p, center) < radius + 1e-6; } // 返回最小包围球的半径和圆心 void minSphere(vector<Point3d>& points, double& radius, Point3d& center) { int n = points.size(); if (n == 0) { radius = 0; center = Point3d(0, 0, 0); return; } else if (n == 1) { radius = 0; center = points[0]; return; } else if (n == 2) { radius = dist(points[0], points[1]) / 2; center = (points[0] + points[1]) / 2; return; } // 随机打乱顺序 random_shuffle(points.begin(), points.end()); // 递归求解 vector<Point3d> rest(points.begin() + 1, points.end()); minSphere(rest, radius, center); if (insideCircle(points[0], center, radius)) return; rest.push_back(points[0]); radius = 0; center = points[0]; for (int i = 0; i < rest.size(); i++) { if (!insideCircle(rest[i], center, radius)) { vector<Point3d> sub(rest.begin(), rest.begin() + i); minSphere(sub, radius, center); if (insideCircle(rest[i], center, radius)) return; rest.erase(sub.begin(), sub.end()); rest.push_back(rest[i]); } } } int main() { // 生成随机点集 vector<Point3d> points; random_device rd; mt19937 gen(rd()); uniform_real_distribution<double> dis(-1.0, 1.0); for (int i = 0; i < 10; i++) { double x = dis(gen); double y = dis(gen); double z = dis(gen); points.push_back(Point3d(x, y, z)); } // 求解最小包围球 double radius; Point3d center; minSphere(points, radius, center); // 绘制点集和最小包围球 Mat img(600, 600, CV_8UC3, Scalar(255, 255, 255)); for (auto p : points) { Point2d p2d(p.x * 200 + 300, p.y * 200 + 300); circle(img, p2d, 2, Scalar(0, 0, 255), -1); } Point2d center2d(center.x * 200 + 300, center.y * 200 + 300); circle(img, center2d, radius * 200, Scalar(0, 255, 0), 2); imshow("Minimum Bounding Sphere", img); waitKey(); return 0; } ``` 这里我们使用了 `Point3d` 类型来表示三维,`minSphere` 函数实现了递归求解最小包围球的过程,`insideCircle` 函数用于判断一个是否在圆内。最后,我们使用 OpenCV 绘制了点集和最小包围球。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值