Results 1 to 13 of 13

Thread: Code for a four point transformation of an image

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Code for a four point transformation of an image

    This code can be used to manipulate an image into any space defined by four corners. Unlike an affine-transform (3 point transformation) which uses a parallelogram shaped space, this 4 point transformation can use absolutely any generic shape that can be defined by four points. Below is this code, split into the two files that I ended up using.

    Code for DPointType.bas
    Code:
    Public Type DPOINT
    X As Double
    Y As Double
    End Type
    Code for FourPointTransform.cls
    Code:
    'Requires DPointType.bas
    
    'The Points array holds 4 points. Below is an explanation of each point.
    'Points(0) is the position that a rectangle's upper left point is mapped to.
    'Points(1) is the position that a rectangle's upper right point is mapped to.
    'Points(2) is the position that a rectangle's lower left point is mapped to.
    'Points(3) is the position that a rectangle's lower right point is mapped to.
    
    Friend Function X2(ByVal X As Double, ByVal Y As Double, ByVal ImgWidth As Double, ByVal ImgHeight As Double, _
    ByRef Points() As DPOINT) As Double
    Dim a As Double
    Dim b As Double
    Dim c As Double
    Dim d As Double
    b = (Points(1).X - Points(0).X) / (ImgWidth - 1)
    d = Points(0).X
    c = (Points(2).X - Points(0).X) / (ImgHeight - 1)
    a = (Points(3).X - (ImgHeight - 1) * c - d - (ImgWidth - 1) * b) / ((ImgWidth - 1) * (ImgHeight - 1))
    X2 = X * (Y * a + b) + Y * c + d
    End Function
    
    Friend Function Y2(ByVal X As Double, ByVal Y As Double, ByVal ImgWidth As Double, ByVal ImgHeight As Double, _
    ByRef Points() As DPOINT) As Double
    Dim a As Double
    Dim b As Double
    Dim c As Double
    Dim d As Double
    b = (Points(2).Y - Points(0).Y) / (ImgHeight - 1)
    d = Points(0).Y
    c = (Points(1).Y - Points(0).Y) / (ImgWidth - 1)
    a = (Points(3).Y - (ImgHeight - 1) * b - (ImgWidth - 1) * c - d) / ((ImgHeight - 1) * (ImgWidth - 1))
    Y2 = Y * (X * a + b) + X * c + d
    End Function
    Use the above class to transform an image in one picture box into a random shape in a second picture box, using the sample code below:
    Code:
    Private Sub TransformImage()
    dim Xfrm as new FourPointTransform
    dim Points(3) as DPOINT
    Points(0).X=100 : Points(0).Y=20
    Points(1).X=300 : Points(1).Y=45
    Points(2).X=115 : Points(2).Y=200
    Points(3).X=290 : Points(3).Y=230
    for y = 0 to Picture1.Height-1
    for x = 0 to Picture1.Width-1
    u = Xfrm.X2(X, Y, Picture1.Width, Picture1.Height, Points)
    v = Xfrm.Y2(X, Y, Picture1.Width, Picture1.Height, Points)
    Picture2.pset(u,v),Picture1.point(x,y)
    next x
    next y
    End Sub
    Or use the above class to transform a portion of an image defined by any random 4-point shape in one picture box to fit correctly into a second picture box. This is the inverse of the above transformation. The code is very similar to the above, with just a few changes. See the code below
    Code:
    Private Sub InverseTransformImage()
    dim Xfrm as new FourPointTransform
    dim Points(3) as DPOINT
    Points(0).X=100 : Points(0).Y=20
    Points(1).X=300 : Points(1).Y=45
    Points(2).X=115 : Points(2).Y=200
    Points(3).X=290 : Points(3).Y=230
    for y = 0 to Picture2.Height-1
    for x = 0 to Picture2.Width-1
    u = Xfrm.X2(X, Y, Picture2.Width, Picture2.Height, Points)
    v = Xfrm.Y2(X, Y, Picture2.Width, Picture2.Height, Points)
    Picture2.pset(x,y),Picture1.point(u,v)
    next x
    next y
    End Sub

  2. #2
    Fanatic Member
    Join Date
    Mar 2009
    Posts
    804

    Re: Code for a four point transformation of an image

    Nice job Ben. I think this is what MS Paint calls Skew.
    A few recommendations:
    Your TransformImage routine uses arbitrary points on an unknown picture so it is
    hard to see what is happening. Write a little demo that allows the user to
    select 4 points on the destination picture, then do the transformation.
    I would change all the doubles to singles, since your code mixes & matches them.
    Replace the Point & PSet calls with SetPixelV & GetPixel APIs for speed.
    Change all the Widths/Heights to ScaleWidths/ScaleHeights.

    Finally, you don't really need a class for this. Your 2 workhorse functions
    (X2 & Y2) can go in a module along with the Point UDT & the APIs.

  3. #3

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Re: Code for a four point transformation of an image

    Quote Originally Posted by VBClassicRocks View Post
    Nice job Ben. I think this is what MS Paint calls Skew.
    A few recommendations:
    Your TransformImage routine uses arbitrary points on an unknown picture so it is
    hard to see what is happening. Write a little demo that allows the user to
    select 4 points on the destination picture, then do the transformation.
    I would change all the doubles to singles, since your code mixes & matches them.
    Replace the Point & PSet calls with SetPixelV & GetPixel APIs for speed.
    Change all the Widths/Heights to ScaleWidths/ScaleHeights.

    Finally, you don't really need a class for this. Your 2 workhorse functions
    (X2 & Y2) can go in a module along with the Point UDT & the APIs.
    Let me address some of your points
    MSPaint's skew is not like this. It is based on a transform defined by only 3 points called an affine transform. Strangest shape you can get out of that is a parallelogram. Opposing sides are always parallel with an affine transform. With my transform (which I believe is called a "projection transform") it uses 4 points so each of the 4 points of the output shape (or input shape if it's being used as an inverse transform) defines a corner of the quadrangle. This means that you can make the transform shape be ANY 4 sided shape, including a shape in which none of the sides are parallel to any of the other sides. That can NOT be done with an affine transform (such as MSPaint's "skew").


    I am currently workng on a test program that allows you to set the 4 points of the transform shape by just clicking on the image. I'll send post the complete code for it here when it's finished.

    I'm not sure where the SINGLEs are in my code. I've only DIMed DOUBLEs. If I use SINGLEs I'll get more artifacts for loss of precision.

    The test program I am working on is indeed using SetPixel and GetPixel.
    Also for compiling the EXE file I've set some of the special optimizations:
    Remove Array Bounds Checks (because I don't have any array indexes that go over the bounds of an array, so I don't need error checking for this and such checks just slow down the program)
    Remove Integer Overflow Checks (because I don't have any operations that would produce an overflow in any condition, so I don't need error checking on this, and it would just slow down my program)
    Remove Floating Point Error Checks (I'm not expecting to get any INF or NAN or other overflow problems out of the operations in this program, so once again it is just an error check that can only serve to slow down my program)
    Remove Safe Pentium FDIV Checks (completely unnececary as this only applies to Pentium computers, not Pentium Pro, Pentium II, Pentium III, Pentium IIII, or any newer Intel CPUs or any other brand of CPU, and most people now days are not using that ancient CPU that was just called "Pentium", so these Safe Pentium checks are useless for modern computers and could only serve to slow down my program)

    By putting these functions in a class, it allows them to be easily implemented in other programs that use the same algorithm. Also since X2 or Y2 may be defined elsewhere as something else putting them in a class so that you need to call the class, guaranties that there are no conflicts with other possible definitions of X2 and Y2 (maybe in some context these would be variables like Dim X2 as Double, instead of the name of a function). This way you can use X2 as both a variable and a function even, like this:
    Code:
    Dim A As New FourPointTransform
    Dim X2 As Double
    X2 = A.X2(X,Y,Picture1.Width,Picture1.Height,Points)
    If I put these functions into a module or in the Declarations part of a form, they may conflict with variables of the same name. Thus a class is needed to separate them from the "main code" of the program.


    As for ScaleHeight and ScaleWidth, I already have set my pictureboxes to have a scalemode of pixels, and not to have any border (thus the upperleft pixel has coordinates x=0 y=0 and the scalewidth=width and scaleheight=height for my pictureboxes, and this simplifies a LOT of code later on so I have less to type so it physically is quicker to write my program). I don't need to explicitly refer to scalewidth and scaleheight in my pictureboxes.
    Last edited by Ben321; Nov 25th, 2012 at 01:11 AM.

  4. #4

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Re: Code for a four point transformation of an image

    I've finally completed my program. I've attached a zip file with containing my program to this message. It has all the source code and the compiled EXE file. I've included a minor improvement in my code in the class (the implementation in the CLS file in the attached ZIP file now differs slightly from the above pasted code). It now uses the forth point as the lower left corner instead of the lower right corner. This is great because it allows lines to be drawn in the image between the points (not just the corner points) to better help one visualize where the pixels are being drawn to (for a forward transformation) or taken from (for an inverse transformation).
    Attached Files Attached Files

  5. #5

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Re: Code for a four point transformation of an image

    Does nobody have a reply to my posting of the program I finally made utilizing this algorithm?

  6. #6
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Thumbs up Re: Code for a four point transformation of an image

    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  7. #7
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: Code for a four point transformation of an image

    Your program works fine! No for small picrutes...so your code must handle the minimum size that no interpolation needed.
    I run it in VB5. You need a memory bitmap for better performance. Maybe I can do it.
    Name:  sample.jpg
Views: 3633
Size:  45.8 KB

  8. #8
    Lively Member
    Join Date
    Mar 2015
    Posts
    104

    Re: Code for a four point transformation of an image

    Looks good. I wonder if the code can be used to deskew scanned images?

  9. #9
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    373

    Re: Code for a four point transformation of an image

    An interesting project.

    Code seems to be tight enough. However, apart from a speed problem, user interface definitely needs some enhancement. Below are a few small suggestions:

    -- For a demo project in a code bank, a picture should be readily available there, rather than being availed through a Clipboard button.

    -- Have diagonal lines on the picture for user to see that the original center point remains relatively in the center after each operation, as this is critical in the transformation.

    -- Provide nodes at four corners for user to drag.

    A sample screenshot is appended below:
    Attached Images Attached Images  

  10. #10

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Re: Code for a four point transformation of an image

    Some other examples here appear to take perspective into account (trapazoid transform makes parts of the image look farther away). My code simply stretches the image to fit the arbitrarily defined shape, but no perspective effect is imparted.

  11. #11
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,817

    Re: Code for a four point transformation of an image

    Hi Ben,

    Yes, very nice work.

    Also, off the top of my head, I'm not sure this is something that can be done with the GDI+, so nice addition.

    It is important to realize though that this isn't a 3D transform. It's a true 2D transform.

    It might be fun though to get into 3D transforms, with all the transformation matrices, linear algebra, and manipulation of quaternions that goes along with it. However, I'm concerned about whether or not VB6 is close enough to the CPU (and GPU) to get it done with the speed that's necessary. To a large degree, that's what the GDI+ and extending into the DirectX libraries is all about, with the DirectX connections to the GPU that just isn't possible with VB6.

    Just for fun, I've attached a VB6 and DirectX project I was playing around with a while back. Basically, it's a Block sphere that can be rotated by dragging it around with the mouse. However, to make it run, you will need DirectX-8 for VB6 installed on your machine (a registered copy of dx8vb.dll from Microsoft). I'll leave you on your own to get that if you're interested.

    Keep up the excellent coding,
    Elroy

    EDIT: Also, even though it won't be fast, I've never found anything wrong with coding this stuff up in straight-up VB6, just for the experience of it if nothing else. I've still got my pic rotation code around somewhere from before the GDI was available.
    Attached Files Attached Files
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  12. #12
    New Member
    Join Date
    Jan 2018
    Posts
    1

    Re: Code for a four point transformation of an image

    Hi Ben321,

    Just wondering if you could re-post the link/attached files for your program - the link doesn't work anymore - I've been looking at EmguCV for a similar function, but the library is massive and a little bit buggy based on target platforms (x86, x64, any cpu) in vb.net. I'm also using Aforge.NET, however that doesn't have anything for 4 point transformations, but is pretty good at shape recognition (which I was wanting to use to identify a shapes points and then perform a transform). I'm really just after something pretty simple and straight forward for the transform.

    Regards,

    Dave

  13. #13
    New Member
    Join Date
    Nov 2021
    Posts
    1

    Re: Code for a four point transformation of an image

    Quote Originally Posted by Ben321 View Post
    I've finally completed my program. I've attached a zip file with containing my program to this message. It has all the source code and the compiled EXE file. I've included a minor improvement in my code in the class (the implementation in the CLS file in the attached ZIP file now differs slightly from the above pasted code). It now uses the forth point as the lower left corner instead of the lower right corner. This is great because it allows lines to be drawn in the image between the points (not just the corner points) to better help one visualize where the pixels are being drawn to (for a forward transformation) or taken from (for an inverse transformation).
    Hi Ben I'm keen to test your 4 point image transform code. The zip attachment appears broken. Do you mind reposting it if you still have it? Cheers.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width