// 构造函数 public FaceTransformation(string source_path, string face_path) { _source_path = source_path; _source_points_path = source_path.Split('.')[0] + ".txt"; _source = new ImageIO(source_path); _source.LockBits(); _source_points = this.LoadPoints(this.Source_points_path); _source_marked = this.MarkPoints(this.Source, this.Source_points); _face_path = face_path; _face_points_path = face_path.Split('.')[0] + ".txt"; _face = new ImageIO(face_path); _face.LockBits(); _face_points = this.LoadPoints(this.Face_points_path); _face_marked = this.MarkPoints(this.Face, this.Face_points); _facePointsAffined = this.AffineTransformation(); _TPS_transform_matrix = this.TPSTransformMatrix(); _source.UnlockBits(); _face.UnlockBits(); }
// TPS变换,输入为新图像中的坐标,输出为原图像中的坐标 public MyMatrix TPSProcessMatrix(double x, double y) { double[,] processMatrixData = new double[71, 1]; Parallel.For(0, 71, i => { if (i < 68) { processMatrixData[i, 0] = RadialBasisFunction(this.FacePointsAffined[2 * i], x, this.FacePointsAffined[2 * i + 1], y); } else { switch (i) { case 68: { processMatrixData[i, 0] = 1; break; } case 69: { processMatrixData[i, 0] = x; break; } case 70: { processMatrixData[i, 0] = y; break; } } } }); MyMatrix processMatrix = new MyMatrix(processMatrixData, 71, 1); MyMatrix process = new MyMatrix(processMatrix); return(process); }
// 矩阵乘法 public MyMatrix Multiply(MyMatrix myMatrix) { if (this.Column == myMatrix.Row) { double[,] processData = new double[this.Row, myMatrix.Column]; for (int i = 0; i < this.Row; i++) { for (int j = 0; j < myMatrix.Column; j++) { processData[i, j] = 0; for (int m = 0; m < this.Column; m++) { processData[i, j] += this.GetMatrix_data()[i, m] * myMatrix.GetMatrix_data()[m, j]; } } } return(new MyMatrix(processData, this.Row, myMatrix.Column)); } else { return(null); } }
// TPS变换矩阵求解 private MyMatrix TPSTransformMatrix() { double[][] LMatrixData = new double[71][]; double[][] YMatrixData = new double[71][]; Parallel.For(0, 71, i => { LMatrixData[i] = new double[71]; Parallel.For(0, 71, j => { if ((i < 68) && (j < 68)) { if (i == j) { LMatrixData[i][j] = 0; } else { LMatrixData[i][j] = RadialBasisFunction(this.FacePointsAffined[2 * i], this.FacePointsAffined[2 * j], this.FacePointsAffined[2 * i + 1], this.FacePointsAffined[2 * j + 1]); } } else if ((i < 68) && (j >= 68)) { switch (j) { case 68: LMatrixData[i][j] = 1; break; case 69: LMatrixData[i][j] = this.FacePointsAffined[2 * i]; break; case 70: LMatrixData[i][j] = this.FacePointsAffined[2 * i + 1]; break; } } else if ((i >= 68) && (j < 68)) { switch (i) { case 68: LMatrixData[i][j] = 1; break; case 69: LMatrixData[i][j] = this.FacePointsAffined[2 * j]; break; case 70: LMatrixData[i][j] = this.FacePointsAffined[2 * j + 1]; break; } } else { LMatrixData[i][j] = 0; } }); YMatrixData[i] = new double[2]; if (i < 68) { YMatrixData[i][0] = this.Source_points[2 * i]; YMatrixData[i][1] = this.Source_points[2 * i + 1]; } else { YMatrixData[i][0] = 0; YMatrixData[i][1] = 0; } }); MyMatrix LMatrix = new MyMatrix(LMatrixData); MyMatrix YMatrix = new MyMatrix(YMatrixData); MyMatrix TransformMatrix = new MyMatrix(LMatrix.Inverse().Multiply(YMatrix).Transpose()); return(TransformMatrix); }
// 转换函数,输入为新图像位置,输出为原图像对应的位置 private Poseition TransformFunction(double x, double y) { switch (this.ProcessOption.Transform) { // 旋转扭曲,使用题目给出的函数计算 case Transform.Distortion: { if (this.DistortionParameter == null) { return(null); } else { double new_x = x; double new_y = y; double distance = Math.Sqrt(Math.Pow(Convert.ToDouble(x - this.DistortionParameter.DistortionCenter_x) / this.DistortionParameter.Factor_x, 2) + Math.Pow(Convert.ToDouble(y - this.DistortionParameter.DistortionCenter_y) / this.DistortionParameter.Factor_y, 2)); if (distance < this.DistortionParameter.DistortionRadius) { double distortionDegree = -this.DistortionParameter.MaxDistortionDegree * ((this.DistortionParameter.DistortionRadius - distance) / this.DistortionParameter.DistortionRadius); new_x = ((x - this.DistortionParameter.DistortionCenter_x) * Math.Cos(distortionDegree) - (y - this.DistortionParameter.DistortionCenter_y) * Math.Sin(distortionDegree)) + this.DistortionParameter.DistortionCenter_x; new_y = ((x - this.DistortionParameter.DistortionCenter_x) * Math.Sin(distortionDegree) + (y - this.DistortionParameter.DistortionCenter_y) * Math.Cos(distortionDegree)) + this.DistortionParameter.DistortionCenter_y; } return(new Poseition(new_x, new_y)); } } // * 畸变矫正,题目给出的函数实现效果不佳,查询网络相关实现方法后,学习、改进并实现了自己的转换方法 case Transform.Warp: { if (this.WarpParameter == null) { return(null); } else { double new_x = x; double new_y = y; double distance = Math.Sqrt(Math.Pow(Convert.ToDouble(x - this.WarpParameter.WarpCenter_x) / this.WarpParameter.Factor_x, 2) + Math.Pow(Convert.ToDouble(y - this.WarpParameter.WarpCenter_y) / this.WarpParameter.Factor_y, 2)); if (distance != 0) { double k = this.WarpParameter.WarpFactor * (Math.Pow(distance, 2) / this.WarpParameter.WarpScale); new_x = (1 + k) * (x - this.WarpParameter.WarpCenter_x) + this.WarpParameter.WarpCenter_x; new_y = (1 + k) * (y - this.WarpParameter.WarpCenter_y) + this.WarpParameter.WarpCenter_y; } return(new Poseition(new_x, new_y)); } } // TPS变换,使用题目给的变换方法并做了相关改进,详见 FaceTransformation.cs case Transform.TPS: { MyMatrix newPosition = new MyMatrix(this.FaceTransformation.TPS_transform_matrix.Multiply(this.FaceTransformation.TPSProcessMatrix(x, y))); return(new Poseition(newPosition.GetMatrix_data()[0, 0], newPosition.GetMatrix_data()[1, 0])); } // 无变换,直接插值 case Transform.None: { return(new Poseition(x, y)); } default: return(null); } }