Homography转换代码

时间:2015-08-09 18:35:23

标签: c# transform homography homogenous-transformation

我正在尝试执行此算法的c#实现

http://www.corrmap.com/features/homography_transformation.php

但结果并不正确。例如,我试图扭曲这个图像: enter image description here

它看起来像这个

enter image description here

这是我的c#实现代码:

using System;
using System.Collections.Generic;
using System.Drawing;

namespace CardMaker
{
    class Perspective : Transformer
    {
        public override void DrawShape(int width, int height, Shape original, Shape warped, Dictionary<Point, Point> mapping)
        {
            double xOff = original.GetTopLeftPixel().GetX();
            double yOff = original.GetTopLeftPixel().GetY();
            double offset = original.GetTopRightPixel().GetX() - original.GetTopLeftPixel().GetX();

            double oTopLeftX = 0;
            double oTopLeftY = 0;
            double oTopRightX = (original.GetTopRightPixel().GetX() - xOff) / offset;
            double oTopRightY = (original.GetTopRightPixel().GetY() - yOff) / offset;
            double oBottomRightX = (original.GetBottomRightPixel().GetX() - xOff) / offset;
            double oBottomRightY = (original.GetBottomRightPixel().GetY() - yOff) / offset;
            double oBottomLeftX = (original.GetBottomLeftPixel().GetX() - xOff) / offset;
            double oBottomLeftY = (original.GetBottomLeftPixel().GetY() - yOff) / offset;
            double wTopLeftX = (warped.GetTopLeftPixel().GetX() - xOff) / offset;
            double wTopLeftY = (warped.GetTopLeftPixel().GetY() - yOff) / offset;
            double wTopRightX = (warped.GetTopRightPixel().GetX() - xOff) / offset;
            double wTopRightY = (warped.GetTopRightPixel().GetY() - yOff) / offset;
            double wBottomRightX = (warped.GetBottomRightPixel().GetX() - xOff) / offset;
            double wBottomRightY = (warped.GetBottomRightPixel().GetY() - yOff) / offset;
            double wBottomLeftX = (warped.GetBottomLeftPixel().GetX() - xOff) / offset;
            double wBottomLeftY = (warped.GetBottomLeftPixel().GetY() - yOff) / offset;

            double[,] X = new double[8, 8];
            double[] Y = new double[8];

            X[0, 0] = wTopLeftX;
            X[1, 0] = wTopLeftY;
            X[2, 0] = 1;
            X[3, 0] = 0;
            X[4, 0] = 0;
            X[5, 0] = 0;
            X[6, 0] = -wTopLeftX * oTopLeftX;
            X[7, 0] = -wTopLeftY * oTopLeftX;

            X[0, 1] = wTopRightX;
            X[1, 1] = wTopRightY;
            X[2, 1] = 1;
            X[3, 1] = 0;
            X[4, 1] = 0;
            X[5, 1] = 0;
            X[6, 1] = -wTopRightX * oTopRightX;
            X[7, 1] = -wTopRightY * oTopRightX;

            X[0, 2] = wBottomRightX;
            X[1, 2] = wBottomRightY;
            X[2, 2] = 1;
            X[3, 2] = 0;
            X[4, 2] = 0;
            X[5, 2] = 0;
            X[6, 2] = -wBottomRightX * oBottomRightX;
            X[7, 2] = -wBottomRightY * oBottomRightX;

            X[0, 3] = wBottomLeftX;
            X[1, 3] = wBottomLeftY;
            X[2, 3] = 1;
            X[3, 3] = 0;
            X[4, 3] = 0;
            X[5, 3] = 0;
            X[6, 3] = -wBottomLeftX * oBottomLeftX;
            X[7, 3] = -wBottomLeftY * oBottomLeftX;

            X[0, 4] = 0;
            X[1, 4] = 0;
            X[2, 4] = 0;
            X[3, 4] = wTopLeftX;
            X[4, 4] = wTopLeftY;
            X[5, 4] = 1;
            X[6, 4] = -wTopLeftX * oTopLeftY;
            X[7, 4] = -wTopLeftY * oTopLeftY;

            X[0, 5] = 0;
            X[1, 5] = 0;
            X[2, 5] = 0;
            X[3, 5] = wTopRightX;
            X[4, 5] = wTopRightY;
            X[5, 5] = 1;
            X[6, 5] = -wTopRightX * oTopRightY;
            X[7, 5] = -wTopRightY * oTopRightY;

            X[0, 6] = 0;
            X[1, 6] = 0;
            X[2, 6] = 0;
            X[3, 6] = wBottomRightX;
            X[4, 6] = wBottomRightY;
            X[5, 6] = 1;
            X[6, 6] = -wBottomRightX * oBottomRightY;
            X[7, 6] = -wBottomRightY * oBottomRightY;

            X[0, 7] = 0;
            X[1, 7] = 0;
            X[2, 7] = 0;
            X[3, 7] = wBottomLeftX;
            X[4, 7] = wBottomLeftY;
            X[5, 7] = 1;
            X[6, 7] = -wBottomLeftX * oBottomLeftY;
            X[7, 7] = -wBottomLeftY * oBottomLeftY;

            Y[0] = oTopLeftX;
            Y[1] = oTopRightX;
            Y[2] = oBottomRightX;
            Y[3] = oBottomLeftX;
            Y[4] = oTopLeftY;
            Y[5] = oTopRightY;
            Y[6] = oBottomRightY;
            Y[7] = oBottomLeftY;

            Solver.Solve(X, Y);
            double a = Y[0], b = Y[1], c = Y[2], d = Y[3], e = Y[4], f = Y[5], g = Y[6], h = Y[7];

            List<Pixel> warpedPixels = warped.GetPixels();
            foreach (Pixel pixel in warpedPixels)
            {
                double pX = (pixel.GetX() - xOff) / offset;
                double pY = (pixel.GetY() - yOff) / offset;

                double t1_ = (a * pX + b * pY + c);
                double t2_ = (g * pX + h * pY + 1);
                double t3_ = (d * pX + e * pY + f);

                if (t2_ == 0)
                {
                    t2_ = 0.000000001;
                }

                double originalX_ = t1_ / t2_;
                double originalY_ = t3_ / t2_;

                int originalX = Math.Min(width - 1, Math.Max(0, Convert.ToInt32(Math.Max(0, Math.Min(width, originalX_ * offset + xOff)))));
                int originalY = Math.Min(height - 1, Math.Max(0, Convert.ToInt32(Math.Max(0, Math.Min(height, originalY_ * offset + yOff)))));

                mapping.Add(new Point(pixel.GetX(), pixel.GetY()), new Point(originalX, originalY));
            }
        }
    }
}

我所做的是拍摄两个形状对象,分别代表方形(原始)和四边形(扭曲)。我将方块转换为位置(0,0)并将其缩放为单位平方。这些是正确的坐标点btw,因为我使用两个具有相同数据的其他转换方法,并且它工作正常。然后我使用这种方法转换点。我也使用高斯消元法求解系数,我知道它有效,因为它适用于其他两种方法。

有谁知道可能是什么问题?

由于

0 个答案:

没有答案