当前位置: 首页> 汽车> 报价 > 手机屏幕贴合项目(回顾和总结,那个最重要的算法,开头)

手机屏幕贴合项目(回顾和总结,那个最重要的算法,开头)

时间:2025/7/8 23:05:31来源:https://blog.csdn.net/ganggangwawa/article/details/140063606 浏览次数: 0次

接住上一节,我们先看算法:

CulcMultiViewOffset(MY_FIRSTRESULT&reFirst, float&resX, float&resY, float&resAng, float* pLenghtUp, float* pLenghtDn , void* Points, unsigned int count, float Xr, float Yr, MyOffset Offset, int flag )
{
    float DnToXAngle=0,array_angle[4];
    float DnbaAngle=0;
    float x=0,y=0;
    int j=0;
    unsigned int i=0;
    if( Points == NULL )
        return -1;

    float sumX=0, sumY=0, sumA=0;
    Vector* pPoints = (Vector*) Points;

    Vector* VectUp = new Vector[count];            //跌偿娩秖ボ, 
    Vector* VectDn = new Vector[count];            //跌偿娩秖ボ
    float* deltaA = new float[count];            //璸衡眔癸莱娩Жà
    Vector rotatecenter(Xr, Yr);                //跌偿臂锣いみ
    Vector* VectDnRt = new Vector[count];        //跌偿郴翴癸莱跌偿臂锣いみ秖
    Vector* UpCorner = new Vector[count];        //跌偿畒夹玒畒夹
    Vector* DnCorner = new Vector[count];        //跌偿畒夹玒畒夹
    //眔跌偿畒夹
    for( i=0; i<count; i++ )
    {
        UpCorner[i] = *( pPoints+i );
        DnCorner[i] = *( pPoints+count+i );
    }

    DnToXAngle=0;
    for(i=0; i<count; i++)
    {
        j=(i+1)%count;
        if (i%2==0)
            array_angle[i]=atan((UpCorner[j].a-UpCorner[i].a)/(UpCorner[j].b-UpCorner[i].b))*180/PI;
        else
            array_angle[i]=abs(abs(atan((UpCorner[j].a-UpCorner[i].a)/(UpCorner[j].b-UpCorner[i].b))*180/PI)-90);
        DnToXAngle+=array_angle[i];
    }
    DnToXAngle/=count;

    Offset.dy=-Offset.dy;

    //X=a*cos-b*sin;
    //Y=a*sin+b*cos;
    x=Offset.dx*cos(DnToXAngle*PI/180)-Offset.dy*sin(DnToXAngle*PI/180);
    y=-(Offset.dx*sin(DnToXAngle*PI/180)+Offset.dy*cos(DnToXAngle*PI/180));

    reFirst.UpX=x;
    reFirst.UpY=y;

    for(i=0; i<count; i++)
    {
        UpCorner[i].a+=x;
        UpCorner[i].b+=y;
    }
    //ぃノσ納翴丁竚闽玒
    for( i=0; i<count; i++ )
    {
        int j=(i+1)%count;
        VectUp[i] = UpCorner[j] - UpCorner[i];    //超娩娩秖, 跌偿
        VectDn[i] = DnCorner[j] - DnCorner[i];    //超娩娩秖, 跌偿
        //璸衡`跌偿癸莱娩Жà, 眖跌偿秖臂锣跌偿癸莱秖Жà
        deltaA[i] = /*pow(-1.0,i)**/VectDn[i].angle( VectUp[i] );//癴皐タ,抖皐璽

        *(pLenghtUp+i) = VectUp[i].length();
        
        *(pLenghtDn+i) = VectDn[i].length();

        sumA += deltaA[i];
    }
    resAng = ((sumA/count)*180.00)/PI;
    resAng = resAng - Offset.dang;//
    
    if (!(abs(resAng)>=0))
    {
        i=0;
    }
    //臂锣畒夹, 沮璸衡à臂锣秖臂锣穝秖, 盢跌偿い郴翴瞅露臂锣いみ锣笆.
        for( i=0; i<count; i++ )
        {
          
                VectDnRt[i] = *(pPoints+count+i) - rotatecenter;
                //秖臂锣
                VectDnRt[i] = VectDnRt[i].rotate( (resAng*PI)/180.00 );
                //穝臂锣跌偿郴翴畒夹
                DnCorner[i] = VectDnRt[i] + rotatecenter;
                if( flag == 1)
                {    //盢臂锣畒夹挡狦硄筁pPoint把计
                    *( pPoints+count+i ) = DnCorner[i];
                }
                //璸衡臂锣熬畉
                sumX += (UpCorner[i]-DnCorner[i]).a;
                sumY += (UpCorner[i]-DnCorner[i]).b;
        
        }    
    resX = sumX/count;
    resY = sumY/count;
    
    delete[] VectUp;
    delete[] VectDn;
    delete[] deltaA;
    delete[] VectDnRt;
    delete[] DnCorner;
    delete[] UpCorner;
    return 0;
}

看上去参数一大堆,挺吓人的,有时候就会被这种纸老虎吓住。

我们该怎样学?最好是在现场,因为现场生产是正常的,所以,里头整几个断点,看看 m_WorldPoint[2][4]进入这个算法,最后怎样了,现在看来,是很好说清楚了:

第一,    //X=a*cos-b*sin;
    //Y=a*sin+b*cos;看到这个公式,显然是坐标旋转了一个角度的计算方法

第二,我们看是什么坐标用到了这个公式,m_WorldPoint[2][4]就是算法中的pPoints,counts=4,所以,UpCorner就是上面矩形四个点,DnCorner就是下面矩形四个点。UpCorner四个点构成四条线,然后每相邻线求角度,明明是矩形为什么要算四个角的和,然后还除以4,不就是90度吗?这一点还是很困惑的,实际是产品看上去很完美的是矩形,但实际不是,你要是还在几何矩形概念里,就着上了!

多年以后,再次看这一段坐标变换的代码,尴尬的是,又看不懂了,不过轻微还有点印象是,这里的(x,y)=(0,0),当年好像设断点监控过,所以这一段代码就是迷魂汤,是个陷阱,为什么这样呢?难道与设备状态有关,自从我们接手后,这种状态就无用了?或许就是

   UpCorner[i].a+=x;//0
        UpCorner[i].b+=y;//0

好在我正常运行的改进对角线四点程序和这个出入不大,显然已经没有这一段,说明,我的记忆还行,虽然研究这个公式花了时间,没用了,但如果你从头写视觉软件,一刻也离不开这个公式.

第三,关键来了,   VectUp[i] = UpCorner[j] - UpCorner[i];   
        VectDn[i] = DnCorner[j] - DnCorner[i]; 这个把8个坐标变成了八个向量,有方向和长度,

这八个向量,分成上下一一对应两组,做了什么呢?

第四,求一一对应两个向量角度偏差,一共四组,求和后,取了均值角度偏差。

第五,以下矩形中心,和这个均值角度偏差,旋转下矩形四条边(四个向量),然后找出上下矩形平均x的偏差,平均y偏差

那么最后,就是以上矩形为标准,下矩形旋转和平移(均值角度偏差resAng,平均x的偏差resX ,平均y偏差resY ),这些数据都已经算出来,做最后的贴合。

这个算法中干扰很多,但影响不大,这就是现场的算法,多人经手,没人敢动,就一直保留下来了,这就是他们现在说的代码“屎山”。我们项目主题中的算法粗框架已经讲完了,如果你去看算法外的细节,又是一堆和现场机器运行状态相关的许多不敢轻易下手改动的代码。

算法相对代码“屎山”还是简单,起码他是数学可以保证的。需要强调的是,只说算法,实际

   //X=a*cos-b*sin;
    //Y=a*sin+b*cos;与

   VectDnRt[i] = VectDnRt[i].rotate( (resAng*PI)/180.00 );在数学上是无差别的

这两个公式在我写megauging中一直在保驾护航,或许是走入社会开始学习的先入为主吧!

下一节,我们学习一下工程中图像处理类对ni的封装,待续

关键字:手机屏幕贴合项目(回顾和总结,那个最重要的算法,开头)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: