Search code examples
c#imagemagickemgucv

Emgu Image Transformation - Keystone


I am currently trying to keystone and image from a fish eye lens camera. The camera points off to the distance down a path and i get soemthing like this where the path is in the middle -

View from Camera

What i need to achieve is to transfomr it to this -

Image result

I was lookign to do it with ImageMagick but sturglling to turn a Mat or EMgu Image into a ImageMagick Image -

Image<Rgb, byte> image_to_warp = _frame.ToImage<Rgb, Byte>();

int x0 = 0;
int y0 = 0;
int x1 = _frame.Width;
int y1 = 0;
int x2 = _frame.Width;
int y2 = _frame.Height;
int x3 = 0;
int y3 = _frame.Height;

int newX0 = (Int32)new_x0.Value;
int newY0 = (Int32)new_y0.Value;
int newX1 = (Int32)new_x1.Value;
int newY1 = (Int32)new_y1.Value;
int newX2 = (Int32)new_x2.Value;
int newY2 = (Int32)new_y2.Value;
int newX3 = (Int32)new_x3.Value;
int newY3 = (Int32)new_y3.Value;

using (MagickImage image_warped = new MagickImage(image_to_warp))
{
    image_warped.Distort(DistortMethod.Perspective, new double[] { x0, y0, newX0, newY0, x1, y1, newX1, newY1, x2, y2, newX2, newY2, x3, y3, newX3, newY3 });
}

Then the plan was to just manually adjust the corner until i got it straight. Is there an easier way to do this directly with Emgu, or is the above along the right lines and how would you covnert the image files. I have looked at so many options on how to ahcive this, but not getting nay results so far.

Thanks for any help!

EDIT: So currently looking at the FindHomography as noted below, but really struggle to see how it relates the two sets of points. I currenty have this - camCapture.Image = _frame;

            `PointF[] pts_src = new PointF[] { new PointF((0 + newX0), (0 + newY0)), new PointF((_frame.Width + newX1), (0 + newY1)), new PointF((_frame.Width + newX2), (_frame.Height + newY2)), new PointF((_frame.Height + newX3), (0 + newY3)) };
            PointF[] pts_dst = new PointF[] { new PointF(0, 0), new PointF(_frame.Width, 0), new PointF(_frame.Width, _frame.Height), new PointF(_frame.Height, 0) };
            Mat h = CvInvoke.FindHomography(pts_src, pts_dst);
            CvInvoke.WarpPerspective(_frame, _frame, h, _frame.Size);`

Basically using a Numeric Up down, to get the newX0, new y0, values, and would expect the image to warp by one pixel at a time, it really doesn do that unless im missing something?

EDIT: this does work as i expected, however, the code above i posted was incorrect and should read - `camCapture.Image = _frame;

PointF[] pts_src = new PointF[] { new PointF((0 + newX0), (0 + newY0)), new PointF((_frame.Width + newX1), (0 + newY1)), new PointF((_frame.Width + newX2), (_frame.Height + newY2)), new PointF((0 + newY3),(_frame.Height + newX3)) }; PointF[] pts_dst = new PointF[] { new PointF(0, 0), new PointF(_frame.Width, 0), new PointF(_frame.Width, _frame.Height), new PointF(0, _frame.Height) }; Mat h = CvInvoke.FindHomography(pts_src, pts_dst); CvInvoke.WarpPerspective(_frame, _frame, h, _frame.Size);


Solution

  • You want to use openCV's 'cvFindHomography', with details here

    Here's a good site with examples in C++ and Python, as well as the projective-plane geometry behind it all.