opencv 学习(5)拐点的查找

  引言


  图像处理过程中,拐点是重要的特征点之一。进行图像的分析时,拐点是一重要的研究方向。

拐点的形象解释:拐点,又称反曲点,在数学上指改变曲线向上或向下方向的点,直观地说拐点是使切线穿越曲线的点(即曲线的凹凸分界点)。若该曲线图形的函数在拐点有二阶导数,则二阶导数在拐点处异号(由正变负或由负变正)或不存在。

拐点的定义:若曲线图形在一点由凸转凹,或由凹转凸,则称此点为拐点。直观地说,拐点是使切线穿越曲线的点。若该曲线图形的函数在某点的二阶导数为零或不存在,且二阶导数在该点两侧符号相反,该点即为函数的拐点。这是寻找拐点时最实用的方法之一。

知道了拐点的定义,下面我们来讨论实际中如何获取拐点:

 从图中我们可以清晰的看出拐点的位置。然而在实际的操作当中,我们获取拐点并不是很容易。或者说,我们让计算机获取拐点是需要我们给计算机一个处理方式的。在此处,我所介绍的方法,仅仅只是一些简单的拐点。我的方式是取点求趋势得拐点。


具体做法:(默认可得轮廓点)

  得到轮廓点之后,我以区间的形式取点,即以一个固定长度取点求其平均值,用这个区间的平均值点来代表整个区间。用取得的平均值点来求当前线段或者弧段的趋势,当趋势改变剧烈时便是一条线段或弧段取完所有可用点的时候。这个时候我们使用线性方程来描述这个趋势即{y=kx+b|x,y->D},我们求其k,b,这样我们便得到了一个线性趋势方程。同理,我们可以得到所有的线性趋势方程。(在这里使用线性的原因仅仅因为趋势没有复杂的变化,并且线性的描述要简单一些)                                      现在我们找到两个趋势方程便可以找到拐点。

y=Kx+B,y=kx+b      取交点(x,y)=((b-B)/(K-k),Kx+B)或x,y)=((b-B)/(K-k),kx+b).取交点,在从轮廓中找到离交点最近的点。这样我们便完成了拐点的寻找。


效果

 

 

 


代码:

/********************************************************************
** 文  件  名:拐点查找(主要内容)
** 创  建  人:yk
** 最后修改时间:2018年11月22日
*********************************************************************/

struct K_and_point
{
	long double K = 0;
	long double X = 0;
	long double Y = 0;
	long double B = 0;
};


bool Bigorsmall(double numberone,double numbertwo)
{
	return  numberone >= numbertwo ? true : false;
}


double point_x[100] = { 0 }, point_y[100] = {0}, dateSum_x=0, dateSum_y = 0;
		int datelen = 0, Recordlen = 0,Switch=0, trend_x=0,trend_y=0,Trend_Switch=0,linelenth=0;
		for (int i = 0; i < a.contours.size(); i++)
		{
			for (int j = 0; j < a.contours[i].size(); j++)
			{
				if (j == 0)
				{
					again:
					point_x[datelen] = a.contours[i][j].x;
					point_y[datelen] = a.contours[i][j].y;
					datelen++;
				}
				dateSum_x += (double)a.contours[i][j].x / (double)Collectionlength;
				dateSum_y += (double)a.contours[i][j].y / (double)Collectionlength;
				Recordlen++;
				if (Recordlen == Collectionlength)
				{
					Recordlen = 0;
						if (Bigorsmall(dateSum_x, point_x[datelen - 1]))
						{
							trend_x = 2;

						}
						else
						{
							trend_x = 1;

						}
						if (Bigorsmall(dateSum_y, point_y[datelen - 1]))
						{
							trend_y = 4;
							
						}
						else
						{
							trend_y = 3;
						}
						Trend_Switch = trend_x + trend_y;
						if((Switch==0)||(Switch==Trend_Switch))
						{ 
							Switch = Trend_Switch;
							point_x[datelen] = dateSum_x;
							point_y[datelen] = dateSum_y;
							dateSum_x = 0;
							dateSum_y = 0;
							datelen++;
						}
						else
						{
							for (int i = 0; i < datelen; i++)
							{
								b[linelenth].X += (long double)point_x[i] / (long double)datelen;
								b[linelenth].Y += (long double)point_y[i] / (long double)datelen;
								
							}
							int re = 0;
							for (int i = 0; i < datelen - 1; i++)
							{
								b[linelenth].K += ((long double)point_y[i + 1] - (long double)point_y[i]) / ((long double)point_x[i + 1] - (long double)point_x[i]);
									re++;
							}
							b[linelenth].K = (long double)b[linelenth].K/(long double)re;
							b[linelenth].B = (long double)(b[linelenth].Y - b[linelenth].X*b[linelenth].K);
							//cout << b[linelenth].K << endl;
							datelen = 0;
							Switch=0;
							dateSum_x = 0;
							dateSum_y = 0;
							linelenth++;
							goto again;
						}
				}
			}
		}
		long double B_x = 0,B_y=0;
		B_x = (long double)(b[1].B - b[0].B) / (long double)(b[0].K - b[1].K);
		B_y = (long double)(b[0].K*B_x + b[0].B);
		Point start(B_x - 10, B_y - 10), end(B_x + 10, B_y + 10);

		YKrectangle(img, start, end, 1);
		cout <<"拐点的X="<< B_x << endl;
		cout << "拐点的Y=" << B_y << endl;
			imshow("END", img);

 

 

 

  • 2
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值