Finding corner coordinates after rotation

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
Kepler
Posts: 6
Joined: 2012-10-25T13:52:36-07:00
Authentication code: 67789

Finding corner coordinates after rotation

Post by Kepler »

I’m writing code in Excel VBA to manipulate scanned maps. I use the distort option to rotate and shear the maps to ensure that north is exactly straight up and that the scale is the same in all directions. It works excellent, but there is a problem: My program needs the X and Y pixel coordinates of the four corners of the map after the operation. However, I have failed to find a solution.

1st idea: Use verbose to get the eight transformation coefficients, like in this code, but I have no clue where to find the message containing the coefficients. It shall go to “Standard error channel”, but what is that when running VBA-code?

Code: Select all

msgs = img.Convert(InputFile, "-virtual-pixel", "background", "-verbose", "+distort", "Projection", _
"0,0,0,0 800,0,800,-100 800,600,800,500 0,600,0,600", OutputFile) 

2nd idea: Get the color of each pixel along the image frame to locate the corner. I tried this, but it is much too time consuming since I run the Convert command for each pixel.

Code: Select all

ImageHeight = img.Identify("-format", "%h", OutputFile)
X = 1
For Y = 1 To ImageHeight
    PixelCoordinates = "%[pixel:p{" & X & "," & Y & "}]"
    msgs = img.Convert(OutputFile, "-format", PixelCoordinates, "info:")
    If msgs <> "white" Then
        CornerY = Y
        Exit Sub
    End If
Next Y
3rd idea: Maybe I can extract each of the four parts with virtual pixel with some kind of magic wand function. And then I can get the width and height of each of these four parts. However, I have not found any possibilities in ImageMagick. Impossible?

4th idea: I write code that will calculate the eight transformation coefficients from the four sets of control points. This is my last option which I have not tried yet.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Finding corner coordinates after rotation

Post by fmw42 »

msgs = img.Convert(InputFile, "-virtual-pixel", "background", "-verbose", "+distort", "Projection", _
"0,0,0,0 800,0,800,-100 800,600,800,500 0,600,0,600", OutputFile)
I do not know the IM APIs, but this command does not seem right to me. There is no distort Projection. And you should likely be using -distort Perspective as it uses control point and not -distort Perspective-Projection.

You should be able to get the coordinates you need from the verbose info. See http://www.imagemagick.org/Usage/distor ... _internals
Kepler
Posts: 6
Joined: 2012-10-25T13:52:36-07:00
Authentication code: 67789

Re: Finding corner coordinates after rotation

Post by Kepler »

Terribly sorry about the confusion about distorsion method; I simply wrote wrong in the message. I have of course used Perspective all the time with success. Correct code:

Code: Select all

msgs = img.Convert(InputFile, "-virtual-pixel", "background", "-verbose", "+distort", "Perspective", _
"0,0,0,0 800,0,800,-100 800,600,800,500 0,600,0,600", OutputFile)
Thanks for your reply, but I have still the problem getting the output from the verbose option.

Meanwhile I will continue to explore idea 4, i.e. to solve the linear equation system.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Finding corner coordinates after rotation

Post by fmw42 »

What API are you using? Have you tried it simply in the command line in a terminal?
Kepler
Posts: 6
Joined: 2012-10-25T13:52:36-07:00
Authentication code: 67789

Re: Finding corner coordinates after rotation

Post by Kepler »

I'm not really sure I understand the question about API; it's simply a VBA macro in Excel 2003.

The macro is doing a lot of things, not only ImageMagick operations. So the distorsion must be a part of this macro why performing the distorsion from the command line is not an option for me.

For example, the reason why I need the corner coordinates is that I must calibrate the map after the distorsion, i.e. establish the link between pixel coordinates and latitude/longitude. And this calibration is also a part of the same macro.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Finding corner coordinates after rotation

Post by fmw42 »

I assume then you are on Windows. What version of IM are you using? If it is old, then some of the -distort perspective parameters have changed.

I am not sure why you cannot test the -verbose aspect of your distort command by just running that command in the command line to verify that works properly.

I assume that your issue is that the command works, but you cannot get the verbose info. If that is the case, then the verbose info is likely going to standard error and not standard out.
Kepler
Posts: 6
Joined: 2012-10-25T13:52:36-07:00
Authentication code: 67789

Re: Finding corner coordinates after rotation

Post by Kepler »

I'm running ImageMagick-6.7.8-Q16 on a Windows XP machine. The verbose option works fine under both Affine and Perspective. I have now added code to my VBA macro to calculate the distorsion coefficients (in my case only four coefficients are non-zero making it trivial). But then I realized I didn't need that info; that I can calculate the corner coordinates with a simple geometry exercise. So the issue is solved. Thanks!
Kepler
Posts: 6
Joined: 2012-10-25T13:52:36-07:00
Authentication code: 67789

Re: Finding corner coordinates after rotation

Post by Kepler »

I can show how I finally managed to get the output from the verbose option when running a image distorsion from Excel VBA. The solution was to use Windows Script Host.

The code below also solved some other of my issues:
a) Problems working with files on an external drive connected to wireless router
b) Problems working with filenames containing Swedish letters
c) Problems running the code on my Windows 7 computer where I always got "Run-time error 429: ActiveX component can't create object"

Code: Select all

Sub DistorsionOfSunset()

Dim WSHShell
Set WSHShell = CreateObject("Wscript.Shell")
Dim CommandIM As String
Dim ProgramFolder As String

SourceFile = "\\READYSHARE\USB_Storage\Sunset.jpg"
TempSourceFile = "C:\Temp\Sunset.jpg"
TempDestinationFile = "C:\Temp\DistortedSunset.png"
DestinationFile = "\\READYSHARE\USB_Storage\DistortedSunset.png"

' Distorsion of sunset.jpg
FileCopy SourceFile, TempSourceFile ' ImageMagick has problem working with files on external drive.
ProgramFolder = "C:\MinaProgram\ImageMagick-6.8.0-Q16\"
CommandIM = "Convert " & TempSourceFile & " -virtual-pixel background -verbose +distort Affine " & """" & "0, 0, 0, 0, 800,0,800,100, 800,600,800,700, 0,600,0,600" & """" & " " & TempDestinationFile
Set WSHProcess = WSHShell.Exec(ProgramFolder & CommandIM)
ExecutionIsCompleted = False
i = 0
Do Until ExecutionIsCompleted
    i = i + 1
    Call WaitNumberOfSeconds(5)
    If WSHProcess.Status = 1 Then
        ExecutionIsCompleted = True
    End If
    If i > 60 Then
        WSHProcess.Terminate
        MsgBox "Process terminated after time-out!"
        Exit Sub
    End If
Loop
ReturnValue = WSHProcess.StdErr.ReadAll
MsgBox "Verbose output: " & ReturnValue

' Get the width of the distorted sunset
CommandIM = "Identify -format %w " & TempDestinationFile
Set WSHProcess = WSHShell.Exec(CommandIM)
ReturnValue = WSHProcess.StdOut.Readline
MsgBox "Image width: " & ReturnValue & " pixel"
FileCopy TempDestinationFile, DestinationFile
Kill TempSourceFile
Kill TempDestinationFile

Set WSHShell = Nothing
Set WSHProcess = Nothing

End Sub
Kepler
Posts: 6
Joined: 2012-10-25T13:52:36-07:00
Authentication code: 67789

Re: Finding corner coordinates after rotation

Post by Kepler »

Forgot the WaitNumberOfSeconds subroutine in the previous reply:

Code: Select all

Sub WaitNumberOfSeconds(NumberOfSeconds As Integer)
waitTime = TimeSerial(Hour(Now()), Minute(Now()), Second(Now()) + NumberOfSeconds)
Application.Wait waitTime
End Sub
Post Reply