使用隐藏第二张图像的最小成本函数去除异常值
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 A
或 Matrix 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);
正是您可以在数小时内查找的那种错误...:-)
最好的祝福,
斯蒂芬
更新
在没有收到我昨天发布的问题的回复后,我自己研究了如何完成矩阵 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 A
或 Matrix B
完整程序代码
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);
正是您可以在数小时内查找的那种错误...:-) 最好的祝福, 斯蒂芬