Exemple #1
0
        /// <summary>
        /// 将ValuePointCollection按照val值从小到大排序
        /// </summary>
        /// <param name="vpCollection">ValuePointCollection</param>
        /// <returns></returns>
        public static ValuePointCollection SortValuePointCollection(ValuePointCollection vpCollection)
        {
            if (vpCollection == null || vpCollection.Count == 0)
            {
                return(new ValuePointCollection());
            }

            int min;

            for (int i = 0; i < vpCollection.Count - 1; i++)
            {
                min = i;
                for (int j = i + 1; j < vpCollection.Count; j++)
                {
                    if (((ValuePoint)vpCollection[j]).Val < ((ValuePoint)vpCollection[min]).Val)
                    {
                        min = j;
                    }
                }
                ValuePoint t = (ValuePoint)vpCollection[min];
                vpCollection[min] = vpCollection[i];
                vpCollection[i]   = t;
            }
            return(vpCollection);
        }
Exemple #2
0
 /// <summary>
 /// 集合中删除元素(线程安全), 必须调用base,否则会造成无限递归
 /// </summary>
 /// <param name="vp"></param>
 public void Remove(ValuePoint vp)
 {
     lock (this.SyncRoot)
     {
         base.Remove(vp);
     }
 }
Exemple #3
0
        /// <summary>
        /// 集合中增加元素(线程安全), 必须调用base,否则会造成无限递归
        /// </summary>
        /// <param name="vp">ValuePoint元素</param>
        public void Add(ValuePoint vp)
        {
            if (vp.GetType() != typeof(ValuePoint))
            {
                throw new Exception("类型不匹配,不能加入集合。");
            }

            lock (this.SyncRoot)
            {
                base.Add(vp);
            }
        }
Exemple #4
0
        /// <summary>
        /// 根据两幅图像金字塔和已选定的初始点,计算整体位移,返回位移值和缩放系数
        /// </summary>
        /// <param name="firstlayercollection">第一幅图像金字塔</param>
        /// <param name="secondlayercollection">第二幅图像金字塔</param>
        /// <param name="ipoints">第一幅图像中选中的初始点</param>
        ///  <param name="wx">计算每个点时,积分邻域横向半径,此值寻找初始点时只需要取1,跟踪时要取的大一些</param>
        /// <param name="wy">计算每个点时,积分邻域纵向半径,此值寻找初始点时只需要取1,跟踪时要取的大一些</param>
        /// <param name="reversebias">反向跟踪时,输出点和原来点之间的距离差阈值(像素值),该差值超过阈值被认为不是好的跟踪点,当被删除,建议取1</param>
        /// <param name="medianbias">每个点的位移与中值位移之间的最大距离(像素值),超过这个距离的点认为是跟踪失败的,建议取10</param>
        /// <param name="scalestep">缩放台阶,缩放系数的变化刻度,如变化差小于0.2的视为不变,大于0.2小于0.4的视为0.2,以此类推</param>
        /// <param name="firstlayerpoints">第一幅图像的最终输出点</param>
        /// <param name="secondlayerpoints">第二幅图像的最终输出点</param>
        /// <returns>位移值和缩放系数</returns>
        public float[] ComputerDisplacement(LayerImageCollection firstlayercollection, LayerImageCollection secondlayercollection, ArrayList ipoints,
                                            float reversebias, // 这个参数不好控制,导致跟踪非常不稳定
                                            int wx, int wy, float medianbias, float scalestep,
                                            ref ArrayList firstlayerpoints, ref ArrayList secondlayerpoints)
        {
            if (ipoints == null || secondlayercollection == null || firstlayercollection == null)
            {
                return(null);
            }

            // 输出结果,前两个维度表示位移,第三个维度表示区域缩放系数
            float[] outvector = new float[3];

            firstlayerpoints  = new ArrayList();
            secondlayerpoints = new ArrayList();

            ArrayList            jpoints       = new ArrayList();
            ValuePointCollection fbPointsArray = new ValuePointCollection();      // 用于计算Forward-Backward的集合,ValuePoint类型的
            ValuePoint           vp            = null;

            foreach (PointF p in ipoints)
            {
                PointF jpoint = TrackPoint(firstlayercollection, secondlayercollection, p, wx, wy);    // 正跟踪,第一幅图跟踪到第二幅图
                PointF ipoint;

                if (jpoint.X >= 0 && jpoint.Y >= 0)
                {
                    vp = new ValuePoint();

                    vp.Ptf1 = p;        // 第一幅图的点加入队列
                    vp.Ptf2 = jpoint;   // 第二幅图的对应点加入队列
                    fbPointsArray.Add(vp);

                    // 这段代码导致跟踪极不稳定
                    ipoint = TrackPoint(secondlayercollection, firstlayercollection, jpoint, wx, wy);                     // 反跟踪,第二幅图跟踪到第一幅图
                    vp.Val = (float)Math.Sqrt((p.X - ipoint.X) * (p.X - ipoint.X) + (p.Y - ipoint.Y) * (p.Y - ipoint.Y)); // 反向跟踪后产生的点与原来点的距离
                    if (vp.Val < reversebias)
                    {
                        fbPointsArray.Add(vp);
                    }
                }
            }

            if (fbPointsArray.Count == 0)
            {
                return(null);
            }

            //// 这段代码不是很合适
            //fbPointsArray = ValuePoint.SortValuePointCollection(fbPointsArray);
            //// 根据Forward-Backward值,去掉一半的不稳定点
            //int arraycont = fbPointsArray.Count;
            //for (int i = arraycont / 2; i < arraycont; i++)
            //{
            //    fbPointsArray.RemoveAt(arraycont / 2);
            //}  // Forward-Backward计算完成

            // 将fbPointsArray用于中值位移计算
            for (int i = 0; i < fbPointsArray.Count; i++)
            {
                vp = fbPointsArray[i];
                // 求每一点的位移值,不作开方减小计算量,不影响结果
                vp.Val = (vp.Ptf2.X - vp.Ptf1.X) * (vp.Ptf2.X - vp.Ptf1.X) + (vp.Ptf2.Y - vp.Ptf1.Y) * (vp.Ptf2.Y - vp.Ptf1.Y);
            }

            fbPointsArray = ValuePoint.SortValuePointCollection(fbPointsArray);

            ValuePoint median_vp = fbPointsArray[fbPointsArray.Count / 2];

            outvector[0] = median_vp.Ptf2.X - median_vp.Ptf1.X;
            outvector[1] = median_vp.Ptf2.Y - median_vp.Ptf1.Y;                   // 中值位移计算完毕

            // 去掉位移偏离中值位移过大的点
            ValuePointCollection tmpCollection = new ValuePointCollection();

            foreach (ValuePoint vpoint in fbPointsArray)
            {
                float dist = (float)Math.Sqrt(Math.Pow(vpoint.Ptf2.X - vpoint.Ptf1.X - median_vp.Ptf2.X + median_vp.Ptf1.X, 2) +
                                              Math.Pow(vpoint.Ptf2.Y - vpoint.Ptf1.Y - median_vp.Ptf2.Y + median_vp.Ptf1.Y, 2));
                if (dist > medianbias)      // 超过中值偏移的点删掉
                {
                    tmpCollection.Add(vpoint);
                }
                else      // 没超过中值位移的点加入图像金字塔
                {
                    firstlayerpoints.Add(vpoint.Ptf1);
                    secondlayerpoints.Add(vpoint.Ptf2);
                }
            }
            foreach (ValuePoint vpoint in tmpCollection)
            {
                fbPointsArray.Remove(vpoint);
            }

            // 计算区域的缩放值
            float[] scales = new float[fbPointsArray.Count - 1];
            for (int i = 0; i < fbPointsArray.Count - 1; i++)
            {
                ValuePoint v1 = fbPointsArray[i];
                ValuePoint v2 = fbPointsArray[i + 1];
                if ((v2.Ptf1.X - v1.Ptf1.X) * (v2.Ptf1.X - v1.Ptf1.X) + (v2.Ptf1.Y - v1.Ptf1.Y) * (v2.Ptf1.Y - v1.Ptf1.Y) == 0)
                {
                    scales[i] = 1;
                }
                else
                {
                    scales[i] = (float)(Math.Sqrt((v2.Ptf2.X - v1.Ptf2.X) * (v2.Ptf2.X - v1.Ptf2.X) + (v2.Ptf2.Y - v1.Ptf2.Y) * (v2.Ptf2.Y - v1.Ptf2.Y)) /
                                        Math.Sqrt((v2.Ptf1.X - v1.Ptf1.X) * (v2.Ptf1.X - v1.Ptf1.X) + (v2.Ptf1.Y - v1.Ptf1.Y) * (v2.Ptf1.Y - v1.Ptf1.Y)));
                }
            }
            outvector[2] = GetMedian(scales);
            if (outvector[2] < 0)
            {
                outvector[2] = 1;
            }
            else
            {
                outvector[2] = 1 + (int)((outvector[2] - 1) / scalestep) * scalestep;
            }

            return(outvector);
        }