使用隐藏第二张图像的最小成本函数去除异常值

Outlier removal using the minimal cost function hiding the second image

更新

在没有收到我昨天发布的问题的回复后,我自己研究了如何完成矩阵 A 和矩阵 B 的矩阵条目,以便我的方法可以计算和 return 一个转换将某个图像 B 与 A 对齐,我从这篇 site 中找到了一篇研究论文,其中列出了矩阵条目的派生。我直接替换了我的 Matrix 条目循环中的表达式,但现在第二个图像稍微删除了异常值,但它在图像 A 的顶部,更新的代码列在下面...

 class ICPTransformation
    {

        public static Transformation ComputeTransformation(List<Point> shp1, List<Point> shp2) {
//create a new 4 by 4 Matrix A for computing the transformation
            PCALib.Matrix A = new PCALib.Matrix(4,4);
//create a new 4 by 1 Matrix for computing the transformation
            PCALib.Matrix B = new PCALib.Matrix(4, 1);
            //iterate through the points stored in the first shape
            for(int i = 0; i < shp1.Count; i++)
            {
                A[0,0] +=2*shp2[i].X*shp2[i].X+2*shp2[i].Y*shp2[i].Y;
                //completing the remaining entries for matrix A
                //it is important to note that matrix A is 4 by 4
                A[0, 1] += 0;
                A[0, 2] += 2 * shp2[i].X;
                A[0, 3] += 2 * shp2[i].Y;
                A[1, 0] += 0;
                A[1, 1] += 2 * shp2[i].Y * shp2[i].Y+2*shp2[i].X*shp2[i].X;
                A[1, 2] += 2 * shp2[i].Y;
                A[1, 3] += -2 * shp2[i].X;
                A[2, 0] += 2 * shp2[i].X;
                A[2, 1] += 2 * shp2[i].Y;
                A[2, 2] += 2;
                A[2, 3] += 0;
                A[3, 0] += 2 * shp2[i].Y;
                A[3, 1] += -2 * shp2[i].X;
                A[3, 2] += 0;
                A[3, 3] += -2;
                //completing the remaining entries for matrix B
                //the dimensions of Matrix B is 4 by one
                B[0, 0] += 2 * shp1[i].X * shp2[i].X + 2 * shp1[i].Y * shp2[i].Y;
                B[1, 0] += 2 * shp1[i].X * shp2[i].Y - 2 * shp2[i].X * shp1[i].Y;
                B[2, 0] += 2 * shp1[i].X;
                B[3, 0] += -2 * shp1[i].Y;


            }
}

任何人都可以帮我从我的代码中删除这个异常,我怀疑它是 Matrix AMatrix B

的 Matrix 条目

完整程序代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using PCALib;

namespace OutlierRemoval
{
    public partial class Form1 : Form
    {
        //declare the lists that will hold the points
        List<Point> Shape1 = new List<Point>();
        List<Point> Shape2 = new List<Point>();
        List<Point> Shape2Transformed = new List<Point>();
        //initialize a panel that will hold the shapes
        
        public Form1()
        {
            InitializeComponent();
            //ADD THE PANEL TO THE FORM\
            //disable the second button until the first images has been initialized
            button2.Enabled = false;
            
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Shape1.Clear();
            Shape2.Clear();
            Point p1a = new Point(20, 30);
            Point p2a = new Point(120,50);
            Point p3a = new Point(160,80);
            Point p4a = new Point(180, 300);
            Point p5a = new Point(100,220);
            Point p6a = new Point(50, 280);
            Point p7a = new Point(20, 140);
            //Hold the Points in an array
            Point[] mypoints = new Point[] {p1a,p2a,p3a,p4a,p5a,p6a,p7a};
            //add the points to the List with one call
            Shape1.AddRange(mypoints);
            //add the points to Shape2
            //define a transformation that will map the shapes 
            //to new shape2
            Transformation t2 = new Transformation();
            t2.A = 1.05;t2.B = 0.05;t2.T1 = 15;t2.T2 = 22;
            Shape2 = ApplyTransformation(t2, Shape1);
            Shape2[2] = new Point(Shape2[2].X + 10, Shape2[2].Y + 3);//change a point
            //add outliers to both shapes
            Point ptOutlier1 = new Point(200, 300);
            Shape1.Add(ptOutlier1);
            Point ptOutlier2 = new Point(270, 160);
            Shape2.Add(ptOutlier2);
            //define the drawing pens with a color of your liking
            Pen pBlue = new Pen(Brushes.Blue, 1);
            Pen pRED = new Pen(Brushes.Red, 1);
            Graphics g = panel1.CreateGraphics();
           // g.DrawLines(pBlue, mypoints);
           // g.DrawLine(pBlue, Shape1[0], Shape1[Shape1.Count - 1]);
            //g.DrawLine(pBlue, Shape1[Shape1.Count - 1], Shape1[Shape1.Count - 2]);
            
           DisplayShape(Shape1, pBlue, g);
           DisplayShape(Shape2, pRED, g);
            //now button two can be cklicked
            button2.Enabled = true;
            
            
        }
        List<Point> ApplyTransformation(Transformation x,List<Point> shape) {
            List<Point> Tlist = new List<Point>();
            foreach (Point c in shape) {
                double xprime = x.A * c.X + x.B * c.Y + x.T1;
                double yprime = x.B * c.X * -1 + x.A * c.Y + x.T2;
                Point ptrans = new Point((int)xprime, (int)yprime);
                Tlist.Add(ptrans);
            }
            return Tlist;
        }
        void DisplayShape(List<Point> Shp,Pen pen, Graphics G)
        {
            Point? prevPoint = null;//nullable
            foreach(Point pt in Shp)
            {
                G.DrawEllipse(pen, new Rectangle(pt.X - 2, pt.Y - 2, 4, 4));
                if (prevPoint != null)
                {
                    G.DrawLine(pen, (Point)prevPoint, pt);
                    
                }
                prevPoint = pt;

            }
            G.DrawLine(pen, Shp[0], Shp[Shp.Count - 1]);

        }

        private void button2_Click(object sender, EventArgs e)
        {
           Transformation T = ICPTransformation.ComputeTransformation(Shape1, Shape2);
            MessageBox.Show("Cost = "+ICPTransformation.computeCost(Shape1,Shape2,T).ToString());
            List<Point> Shape2T = ApplyTransformation(T, Shape2);
            Pen pBlue = new Pen(Brushes.Blue,1);
            Pen pRed = new Pen(Brushes.Red, 1);
            Graphics g = panel2.CreateGraphics();
 
           
            DisplayShape(Shape1,pBlue,g);
            DisplayShape(Shape2T, pRed, g);
        }

        private void button3_Click(object sender, EventArgs e)
        {
           /* Transformation x = new Transformation();
            List<Point> mypoints = ApplyTransformation(x, Shape2);
            Graphics g = panel3.CreateGraphics();
            Pen mypen = new Pen(Brushes.Blue, 1);
            DisplayShape(mypoints, mypen, g);*/
        }
    }
    public class Transformation
    {
        public double A { get; set; }
        public double B { get; set; }
        public double T1 { get; set; }
        public double T2 { get; set; }
    }
    class ICPTransformation
    {

        public static Transformation ComputeTransformation(List<Point> shp1, List<Point> shp2) {
            PCALib.Matrix A = new PCALib.Matrix(4,4);
            PCALib.Matrix B = new PCALib.Matrix(4, 1);
            //iterate through the points stored in the first shape
            for(int i = 0; i < shp1.Count; i++)
            {
                A[0, 0] += 2 * shp2[i].X * shp2[i].X + 2 * shp2[i].Y * shp2[i].Y;
                //completing the remaining entries for matrix A
                //it is important to note that matrix A is 4 by 4
                A[0, 1] += 0;
                A[0, 2] += 2 * shp2[i].X;
                A[0, 3] += 2 * shp2[i].Y;
                A[1, 0] += 0;
                A[1, 1] += 2 * shp2[i].Y * shp2[i].Y + 2 * shp2[i].X * shp2[i].X;
                A[1, 2] += 2 * shp2[i].Y;
                A[1, 3] += -2 * shp2[i].X;
                A[2, 0] += 2 * shp2[i].X;
                A[2, 1] += 2 * shp2[i].Y;
                A[2, 2] += 2;
                A[2, 3] += 0;
                A[3, 0] += 2 * shp2[i].Y;
                A[3, 1] += -2 * shp2[i].X;
                A[3, 2] += 0;
                A[3, 3] += 2;
                //completing the remaining entries for matrix B
                //the dimensions of Matrix B is 4 by one
                B[0, 0] += 2 * shp1[i].X * shp2[i].X + 2 * shp1[i].Y * shp2[i].Y;
                B[1, 0] += 2 * shp1[i].X * shp2[i].Y - 2 * shp2[i].X * shp1[i].Y;
                B[2, 0] += 2 * shp1[i].X;
                B[3, 0] += 2 * shp1[i].Y;


            }
            //get the inverse of the Matrix A
            PCALib.Matrix Ainv =(PCALib.Matrix) A.Inverse;
            //multiply the two matrices to get the transformation
            PCALib.Matrix Res =(PCALib.Matrix) Ainv.Multiply(Ainv);
            Transformation T = new Transformation();
            T.A = Res[0, 0];
            T.B = Res[1, 0];
            T.T1 = Res[2, 0];
            T.T2 = Res[3, 0];
            return T;
            
        }
        public static double computeCost(List<Point> P1List, List<Point> P2List,Transformation T) {
            //initialize the cost to 0
            double cost = 0;
            for (int i = 0; i < P1List.Count; i++) {
                double xprime = T.A * P2List[i].X + T.B * P2List[i].Y + T.T1;
                double yprime = -1 * T.B * P2List[i].X + T.A * P2List[i].Y + T.T2;
                cost += (P1List[i].X-xprime)*(P1List[i].X-xprime)+(P1List[i].Y-yprime)*(P1List[i].Y-yprime);
            }
            return cost;
        }
    }
    public class Tranformation
    {
        public double A { get; set; }
        public double B { get; set; }
        public double T1 { get; set; }
        public double T2 { get; set; }
    }

}

输出

:-) 因此,为了概括:A 和 B 上存在标志问题。 并且,在第 171 行,您有:

PCALib.Matrix Res =(PCALib.Matrix) Ainv.Multiply(Ainv);

你应该有的地方: PCALib.Matrix Res =(PCALib.Matrix) Ainv.Multiply(B);

正是您可以在数小时内查找的那种错误...:-) 最好的祝福, 斯蒂芬