alpha shapes的openCV C++实现

网上只找到了matlab的代码,倒是挺简单的

参考这篇博客

自己写了个C++的实现,有些问题,还没解决,记录下
链接: [Geometry] Alpha Shapes - 原理及我的实现.

结果: 把所有点都连起来了Alt

自己写的C++实现(有问题)

struct Edge
{
	Point2f a;
	Point2f b;
};

class AlphaShape
{
public:
	void AlphaShapes(const float& m_radius, const vector<Point2f> &points, Mat img);
	vector<Point2f> m_points;  // 点集S
	vector<Edge> m_edges;   // 边
private:
};

float squareDistance(Point2f a, Point2f b) {
	return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}

void normalize(Point2f pt)
{	
	float x = pt.x;
	float y = pt.y;

	float flag_x = x > 0 ? 1.0f : -1.0f;
	float flag_y = y > 0 ? 1.0f : -1.0f;

	pt.x =flag_x* x / (sqrt(x * x + y * y));
	pt.y = flag_y * y / (sqrt(x * x + y * y));
}

void AlphaShape::AlphaShapes(const float &m_radius,const vector<Point2f> &points,Mat img)
{
	m_points = points;
	m_edges.clear();
	
	for (int i = 0; i < m_points.size(); i++)
	{
		// k从i+1开始,减少重复计算
		for (int k = i + 1; k < m_points.size(); k++)
		{
			// 跳过距离大于直径的情况
			if (squareDistance(m_points[i],m_points[k]) > 2 * m_radius)
				continue;

			// 两个圆心
			Point2f c1, c2;
			
			// 线段中点
			Point2f center = 0.5*(m_points[i] + m_points[k]);
			//bug在这里
			// 方向向量 d = (x,y)
			Point2f dir = m_points[i] - m_points[k];
 
			// 垂直向量 n = (a,b)  a*dir.x+b*dir.y = 0; a = -(b*dir.y/dir.x)
			Point2f normal;
			normal.y=1;  // 因为未知数有两个,随便给y附一个值1。 

			if (dir.x != 0)
				normal.x=-(normal.y*dir.y) / dir.x;
			else     // 如果方向平行于y轴
			{
				normal.x=1;
				normal.y=0;
			}
			normalize(normal);   // 法向量单位化

			float len = sqrt(m_radius*m_radius - (0.25*(dir.x*dir.x+ dir.y*dir.y)));
			c1 = center + len * normal;
			c2 = center - len * normal;
			cout << "第" << i << "和" << k << "个点" << endl;
			cout << "圆心c1:" << c1.x << " , " << c1.y << endl;
			cout << "圆心c2:" << c2.x << " , " << c2.y << endl;
			//test
			circle(img, c1, m_radius, Scalar(0, 0, 255), 1);
			circle(img, c2, m_radius, Scalar(0, 0, 255), 1);

			// b1、b2记录是否在圆C1、C2中找到其他点。
			bool b1 = false, b2 = false;//false:点在圆外;true:点在圆内
			for (int m = 0; m < m_points.size(); m++)
			{
				if (m == i || m == k)
					continue;

				// 如果都有内部点,不必再继续检查了
				if (b1 == true || b2 == true)
					break;

				if (!b1 && squareDistance( m_points[m],c1) < m_radius)
					b1 = true;
				if (!b2  && squareDistance(m_points[m], c2) < m_radius)
					b2 = true;		
			}

			if (!b1 ||!b2)
			{
				Edge edge;
				edge.a = m_points[i];
				edge.b = m_points[k];

				m_edges.push_back(edge);
			}

		}
	}
}

int main()
{
	Mat image(1000, 1000, CV_8UC3);  //创建一个高200,宽100的灰度图
	vector<Point2f>pts;
	pts.push_back({ 400,400 });
	pts.push_back({ 400,600 });
	pts.push_back({ 600,400 });
	pts.push_back({ 600,600 });
	pts.push_back({ 450,500 });


	for (int i = 0; i < pts.size(); i++)
	{
		circle(image, pts[i], 2, Scalar(0, 0, 255), 2);
	}

	AlphaShape alpha;
	alpha.AlphaShapes(200, pts,image);
	for (int i = 0; i < alpha.m_edges.size(); i++)
	{
		line(image, alpha.m_edges[i].a, alpha.m_edges[i].b, Scalar(0, 255, 0), 2);//bug,除了边缘也画出来了
		cout << alpha.m_edges[i].a.x << " , " << alpha.m_edges[i].a.y << " - "<< alpha.m_edges[i].b.x << " , " << alpha.m_edges[i].b.y<<endl;
	}
	imshow("原图", image);


	waitKey(0);
	return 0;


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值