private void TPSchangeNegativeMatch(Matrix A)//TPS逆变换变形(配准后) { Matrix T = new Matrix(1, 71); Matrix F = new Matrix(1, 2); double distance; progressBar1.Maximum = picWidth2;//进度条显示 progressBar1.Visible = true; for (int i = 0; i < picWidth2; i++) { progressBar1.Value = i; progressBar1.PerformStep(); Application.DoEvents(); for (int j = 0; j < picHeight2; j++) { for (int k = 0; k < 68; k++)//对新图像里的每个点构造矩形求取f(x,y)映射到2图中 { distance = Math.Pow(i - Pic1CorNew[k, 0], 2) + Math.Pow(j - Pic1CorNew[k, 1], 2); if (distance == 0) { T[0, k] = 0; } else { T[0, k] = distance * Math.Log(distance); } } T[0, 68] = 1; T[0, 69] = i; T[0, 70] = j; F = T * A; if (nearest.Checked) { NewPic.SetPixel(i, j, Nearest(F[0, 0], F[0, 1])); } else if (bilinear.Checked) { NewPic.SetPixel(i, j, Bilinear(F[0, 0], F[0, 1])); } else if (bicubic.Checked) { NewPic.SetPixel(i, j, Bicubic(F[0, 0], F[0, 1])); } } } }
private void TPSchangeNegative(Matrix A)//TPS反变换变形 { Matrix T = new Matrix(1, 71); Matrix F = new Matrix(1, 2); double distance; for (int i = 0; i < picWidth2; i++) { for (int j = 0; j < picHeight2; j++) { for (int k = 0; k < 68; k++)//对新图像里的每个点构造矩形求取f(x,y)映射到2图中 { distance = Math.Pow(i - Pic1Cor[k, 0], 2) + Math.Pow(j - Pic1Cor[k, 1], 2); if (distance == 0) { T[0, k] = 0; } else { T[0, k] = distance * Math.Log(distance); } } T[0, 68] = 1; T[0, 69] = i; T[0, 70] = j; F = T * A; if ((int)F[0, 0] < 0 || (int)F[0, 1] < 0 || (int)F[0, 0] >= picWidth2 || (int)F[0, 1] >= picHeight2) { NewPic.SetPixel(i, j, Color.FromArgb(0, 0, 0)); } else { NewPic.SetPixel(i, j, OriginalPic2.GetPixel((int)F[0, 0], (int)F[0, 1])); } } } }
private void SPlinechange2()//将小孩的脸与特朗普对齐后进行的B样条反变换(最终采用) { int Nx = 45, Ny = 45; int max = 0; for (int I = 0; I < 68; I++) { int AbsX = (int)Math.Abs(Pic1CorNewInt[I, 0] - Pic2Cor[I, 0]); int AbsY = (int)Math.Abs(Pic1CorNewInt[I, 1] - Pic2Cor[I, 1]); if (AbsX > max) { max = AbsX; } if (AbsY > max) { max = AbsY; } //Console.WriteLine("AbsX:{0} AbsY:{1}", AbsX, AbsY); } Console.WriteLine("max:{0}", max); if (max <= 45) { Nx = max; Ny = max; } progressBar1.Maximum = 67; progressBar1.Visible = true; for (int I = 0; I < 68; I++) { progressBar1.Value = I; progressBar1.PerformStep(); Application.DoEvents(); int IndexX = (int)(Pic1CorNewInt[I, 0] / Nx);//确定按控制点分片后新特征点所处的Tiles坐标[IndexX,IndexY] int IndexY = (int)(Pic1CorNewInt[I, 1] / Ny); double dx = Pic1CorNewInt[I, 0] - Pic2Cor[I, 0];//目标控制点-初始控制点即为位移 double dy = Pic1CorNewInt[I, 1] - Pic2Cor[I, 1]; double Tx = 0, Ty = 0; //此后循环时的目标点 int dx0 = (int)Pic1CorNewInt[I, 0] - IndexX * Nx; //定义两个校正量,把位移到达的点当做控制点 int dy0 = (int)Pic1CorNewInt[I, 1] - IndexY * Ny; //注意,此时由于引入配准实际会引入误差,因为要求整数点 for (int x1 = -2 * Nx; x1 < 2 * Nx; x1++) { for (int y1 = -2 * Ny; y1 < 2 * Ny; y1++)//开始遍历4*Nx,4*Ny之间的所有受该控制点平移影响的点(x,y) { int x = (int)Pic1CorNewInt[I, 0] + x1; int y = (int)Pic1CorNewInt[I, 1] + y1; int i = (int)((x - dx0) / Nx) - 1; //将默认从(0,0)开始的控制点方格平移为从(2,3)开始 int j = (int)((y - dy0) / Ny) - 1; //计算该受影响的点落在了被控制点分割出的哪个tile内 double u = (double)(x - dx0) / Nx - (int)((x - dx0) / Nx); //计算该受影响的点在所处tile内的offset double v = (double)(y - dy0) / Ny - (int)((y - dy0) / Ny); for (int l = 0; l <= 3; l++) { for (int m = 0; m <= 3; m++) { if ((l + i) == IndexX && (j + m) == IndexY) //对所有遍历的点而言,只有一个控制点的位移不为0,需要计算 { double weight = G(l, u) * G(m, v); //想要优化可以存一张表 Tx = x - weight * dx; Ty = y - weight * dy; } } } if (x < 0 || y < 0 || x >= picWidth2 - 1 || y >= picHeight2 - 1)//目标点超出范围了继续下一次循环 { continue; } else if (Tx < 0 || Ty < 0 || Tx >= picWidth2 - 1 || Ty >= picHeight2 - 1) { NewPic.SetPixel(x, y, Color.FromArgb(0, 0, 0));//越界返回黑色 } else { if (nearest.Checked) { NewPic.SetPixel(x, y, Nearest(Tx, Ty)); } else if (bilinear.Checked) { NewPic.SetPixel(x, y, Bilinear(Tx, Ty)); } else if (bicubic.Checked) { NewPic.SetPixel(x, y, Bicubic(Tx, Ty)); } } } } } }
private void SPlinechange1()//将小孩的脸与特朗普对齐后进行的B样条反变换(对控制点采用最近邻思想,认为某一点发生的位移是离它最近的控制点的位移) { int Nx = 45, Ny = 45; int max = 0; for (int I = 0; I < 68; I++) { int AbsX = (int)Math.Abs(Pic1CorNewInt[I, 0] - Pic2Cor[I, 0]); int AbsY = (int)Math.Abs(Pic1CorNewInt[I, 1] - Pic2Cor[I, 1]); if (AbsX > max) { max = AbsX; } if (AbsY > max) { max = AbsY; } //Console.WriteLine("AbsX:{0} AbsY:{1}", AbsX, AbsY); } Console.WriteLine("max:{0}", max);//取平移的最大值作为控制点间距 if (max <= 45) { Nx = max; Ny = max; } progressBar1.Maximum = 67; progressBar1.Visible = true; for (int I = 0; I < 68; I++) { progressBar1.Value = I; progressBar1.PerformStep(); Application.DoEvents(); int IndexX = (int)(Pic1CorNewInt[I, 0] / Nx);//确定按控制点分片后新特征点所处的Tiles坐标[IndexX,IndexY] int IndexY = (int)(Pic1CorNewInt[I, 1] / Ny); double dx = Pic1CorNewInt[I, 0] - Pic2Cor[I, 0];//目标控制点-初始控制点即为位移 double dy = Pic1CorNewInt[I, 1] - Pic2Cor[I, 1]; if (Pic1CorNewInt[I, 0] - IndexX * Nx > 0.5 * Nx)//对控制点形成的大格点采用最近邻思想,认为某一点发生的位移是离它最近的控制点的位移 { Pic1CorNewInt[I, 0] = (IndexX + 1) * Nx; IndexX = IndexX + 1; } else { Pic1CorNewInt[I, 0] = IndexX * Nx; } if (Pic1CorNewInt[I, 1] - IndexY * Ny > 0.5 * Ny) { Pic1CorNewInt[I, 1] = (IndexY + 1) * Ny; IndexY = IndexY + 1; } else { Pic1CorNewInt[I, 1] = IndexY * Ny; } double Tx = 0, Ty = 0;//此后循环时的目标点 for (int x1 = -2 * Nx; x1 < 2 * Nx; x1++) { for (int y1 = -2 * Ny; y1 < 2 * Ny; y1++)//开始遍历4*Nx,4*Ny之间的所有受该控制点平移影响的点(x,y) { int x = (int)Pic1CorNewInt[I, 0] + x1; int y = (int)Pic1CorNewInt[I, 1] + y1; int i = (int)(x / Nx) - 1; int j = (int)(y / Ny) - 1; //计算该受影响的点落在了被控制点分割出的哪个tile内 double u = (double)(x / Nx) - (int)(x / Nx); //计算该受影响的点在所处tile内的offset double v = (double)(y / Ny) - (int)(y / Ny); for (int l = 0; l <= 3; l++) { for (int m = 0; m <= 3; m++) { if ((l + i) == IndexX && (j + m) == IndexY) //对所有遍历的点而言,只有一个控制点的位移不为0需要计算 { double weight = G(l, u) * G(m, v); //想要优化可以存一张表 Tx = x - weight * dx; Ty = y - weight * dy; } } } if (x < 0 || y < 0 || x >= picWidth2 - 1 || y >= picHeight2 - 1)//目标点超出范围了继续下一次循环 { continue; } else if (Tx < 0 || Ty < 0 || Tx >= picWidth2 - 1 || Ty >= picHeight2 - 1) { NewPic.SetPixel(x, y, Color.FromArgb(0, 0, 0));//越界返回黑色 } else { if (nearest.Checked) { NewPic.SetPixel(x, y, Nearest(Tx, Ty)); } else if (bilinear.Checked) { NewPic.SetPixel(x, y, Bilinear(Tx, Ty)); } else if (bicubic.Checked) { NewPic.SetPixel(x, y, Bicubic(Tx, Ty)); } } } } } }
private void SPlinechange()//将特朗普的脸与小孩对齐后进行的B样条变换 { int max = 0; for (int I = 0; I < 68; I++) { int AbsX = (int)Math.Abs(Pic1Cor[I, 0] - Pic2CorNew[I, 0]); int AbsY = (int)Math.Abs(Pic1Cor[I, 1] - Pic2CorNew[I, 1]); if (AbsX > max) { max = AbsX; } if (AbsY > max) { max = AbsY; } Console.WriteLine("AbsX:{0} AbsY:{1}", AbsX, AbsY); } Console.WriteLine("max:{0}", max); int Nx = max, Ny = max; for (int I = 0; I < 68; I++) { int IndexX = (int)(Pic1Cor[I, 0] / Nx);//确定按控制点分片后新点所处的Tiles坐标[IndexX,IndexY] int IndexY = (int)(Pic1Cor[I, 1] / Ny); double dx = Pic1Cor[I, 0] - Pic2CorNew[I, 0];//目标点-初始点即为位移 double dy = Pic1Cor[I, 1] - Pic2CorNew[I, 1]; //Console.WriteLine("X方向位移dx:{0} Y方向位移dy:{1}", dx, dy); if (dx > 3 * Nx) { dx = 3 * Nx; } if (dy > 3 * Ny) { dy = 3 * Ny; } double Tx = 0, Ty = 0; //目标点 int dx0 = (int)Pic1Cor[I, 0] - IndexX * Nx; //定义两个校正量,把位移到达的点当做控制点 int dy0 = (int)Pic1Cor[I, 1] - IndexY * Ny; //注意,由于引入配准的话实际会引入误差,因为要求坐标为整数点 //Console.WriteLine("dx0:{0} dy0:{1}", dx0, dy0); double[] Param = MatchNegative(); for (int x1 = -2 * Nx; x1 < 2 * Nx; x1++) { for (int y1 = -2 * Ny; y1 < 2 * Ny; y1++)//开始遍历4*Nx,4*Ny之间的所有受该控制点平移影响的点(x,y) { int x = (int)Pic1Cor[I, 0] + x1; int y = (int)Pic1Cor[I, 1] + y1; //Console.WriteLine("此时将平移到的点的坐标 X:{0} Y:{1}", x, y); int i = (int)((x - dx0) / Nx) - 1; //将默认从(0,0)开始的控制点方格平移为从(2,3)开始 int j = (int)((y - dy0) / Ny) - 1; //计算该受影响的点落在了被控制点分割出的哪个tile内 //Console.WriteLine("目标点所属tiles下标[{0},{1}]", i, j); double u = (double)(x - dx0) / Nx - (int)((x - dx0) / Nx);//计算该受影响的点在所处tile内的offset double v = (double)(y - dy0) / Ny - (int)((y - dy0) / Ny); //Console.WriteLine("所属tiles下标[{0},{1}]", i, j); for (int l = 0; l <= 3; l++) { for (int m = 0; m <= 3; m++) { if ((l + i) == IndexX && (j + m) == IndexY) //对所有遍历的点而言,只有一个控制点的位移不为0需要计算 { double weight = G(l, u) * G(m, v); //想要优化可以存一张表 Tx = x - weight * dx; Ty = y - weight * dy; } } } double[] OriginalCor = MatchNegativeInv(Tx, Ty, Param); if (x < 0 || y < 0 || x >= picWidth2 - 1 || y >= picHeight2 - 1) { continue; } else if (OriginalCor[0] < 0 || OriginalCor[1] < 0 || OriginalCor[0] >= picWidth2 - 1 || OriginalCor[1] >= picHeight2 - 1) { NewPic.SetPixel(x, y, Color.FromArgb(0, 0, 0));//越界返回黑色 } else { NewPic.SetPixel(x, y, Nearest(OriginalCor[0], OriginalCor[1])); } } } } }