Scaling a PTO file ..

46 views
Skip to first unread message

Donald Johnston

unread,
Jul 9, 2016, 6:15:06 PM7/9/16
to Hugin Pano
is there a script or program available that can scale the parameters in a PTO file?

I’m thinking of the idea of using a lot of JPG images at 1600 pixels long side to set all CPs, masks, etc so it is quick for Hugin to process and create output images. I can then iterate through different settings/changes and quickly see what the output stitched image will look like.

Then, when all looks well, I’ll recreate JPG (or TIFF) images from my raw images at original resolution (say 7360 pixels long side). It would be nice to then run a script on the PTO file that would scale all i, c, k, etc. lines and output a new PTO file that would work with the higher resolution images.

For example:

pto_scale —scale=7360/1600 —output=upscaled.pto trial.pto

Has anyone done this?

Don ...

Bruno Postle

unread,
Jul 9, 2016, 6:48:46 PM7/9/16
to hugi...@googlegroups.com


On 9 July 2016 23:15:04 BST, Donald Johnston wrote:
>is there a script or program available that can scale the parameters in
>a PTO file?

See ptohalve and prodouble in the Panotools:: Script Perl module, these mostly do what you want.

--
Bruno

Donald Johnston

unread,
Jul 10, 2016, 12:08:25 AM7/10/16
to Hugin Pano
Bruno, thanks for your feedback on this.

I’ve modified you ptodouble to create ptoscale (see below). Will this work? Feel free to do with this as you please.


> #!/usr/bin/perl
> use strict;
> use warnings;
> use Panotools::Script;
> use Getopt::Long;
> use Pod::Usage;
>
> my $scale_pair;
> my $path_output;
> my $help = 0;
>
> GetOptions (’s|scale=s’ => \$scale_pair,
> 'o|output=s' => \$path_output,
> 'h|help' => \$help);
>
> pod2usage (-verbose => 2) if $help;
>
> my $path_pto = shift || pod2usage;
> die "Can't find $path_pto" unless -e $path_pto;
>
> my @Ratio = split ('/', $scale_pair);
> my $R = $Ratio[0] / $Ratio[1];
>
> my $p = new Panotools::Script;
> $p->Read ($path_pto);
>
> $p->Panorama->{w} *= $R;
> $p->Panorama->{h} *= $R;
>
> for my $i (@{$p->Image})
> {
> $i->{w} *= $R;
> $i->{h} *= $R;
> $i->{d} *= $R if $i->{d} =~ /^[-0-9.]+$/;
> $i->{e} *= $R if $i->{e} =~ /^[-0-9.]+$/;
> $i->{Vx} *= $R if $i->{Vx} =~ /^[-0-9.]+$/;
> $i->{Vy} *= $R if $i->{Vy} =~ /^[-0-9.]+$/;
>
> if (defined $i->{S})
> {
> my @S = split (',', $i->{S});
> @S = map {int ($_ * $R)} @S;
> $i->{S} = join ',', @S;
> }
> }
>
> for my $c (@{$p->Control})
> {
> $c->{x} *= $R;
> $c->{y} *= $R;
> $c->{X} *= $R;
> $c->{Y} *= $R;
> }
>
> for my $k (@{$p->Mask})
> {
> my $string = $k->{p};
> $string =~ s/"//g;
> my @p = split (' ', $string);
> @p = map {int ($_ * $R)} @p;
> $k->{p} = '"'. (join ' ', @p) .'"';
> }
>
> $p->Write ($path_output);
>
> exit 0;
>
> __END__
>
> =head1 NAME
>
> ptoscale - rescale a panorama project
>
> =head1 SYNOPSIS
>
> ptoscale [options] --output scaled.pto project.pto
>
> Options:
> -s | --scale Scale ratio (in the format m/n; m = new long side, n = old long side)
> -o | --output Filename of scaled project (can be the the same as the input)
> -h | --help Outputs help documentation
>
> =head1 DESCRIPTION
>
> B<ptoscale> takes a hugin .pto project and scales all pixel dimensions by the ratio given (--scale).
> You will need to rescale the photos to match:
>
> mogrify -geometry {m/n}% *.JPG
>
> Note, this tool is useful in conjunction with the L<ptodouble> and L<ptohalve> tools which
> perform the specific scaling of 2 and 0.5 respectively.
>
> =head1 LICENSE
>
> This program is free software; you can redistribute it and/or
> modify it under the terms of the GNU General Public License
> as published by the Free Software Foundation; either version 2
> of the License, or (at your option) any later version.
>
> =head1 SEE ALSO
>
> L<http://hugin.sourceforge.net/>
>
> L<ptodouble>
>
> L<ptohalve>
>
> =head1 AUTHOR
>
> Donald Johnston; modified from Bruno Postle’s ptodouble - July 2016.
>
> =cut
> --
> A list of frequently asked questions is available at: http://wiki.panotools.org/Hugin_FAQ
> ---
> You received this message because you are subscribed to the Google Groups "hugin and other free panoramic software" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to hugin-ptx+...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/hugin-ptx/6CB7B73D-9353-4E29-B122-9CB6CBCACCD0%40postle.net.
> For more options, visit https://groups.google.com/d/optout.

Donald Johnston

unread,
Jul 10, 2016, 2:47:14 PM7/10/16
to Hugin Pano
Hang on Bruno … I’ve finally got perl working on my MAC; this is my first time with perl programming. I’ve found a few syntax errors in the code but I’ll now test to see if the whole process works after I’ve modified the .pto file with ptoscale.
> To view this discussion on the web visit https://groups.google.com/d/msgid/hugin-ptx/1107DB39-38E8-477B-88B8-EEB25E307D86%40accesscomm.ca.

Bruno Postle

unread,
Jul 10, 2016, 4:58:51 PM7/10/16
to hugi...@googlegroups.com


On 10 July 2016 05:08:22 BST, Donald Johnston wrote:
>Bruno, thanks for your feedback on this.
>
>I’ve modified you ptodouble to create ptoscale (see below). Will this
>work? Feel free to do with this as you please.

Hi Donald, I haven't tried your version yet. The reason why I created two scripts was perhaps over cautious, but I was concerned that although most numbers in a PTO project are floats, critical numbers like image dimensions have to be integers. Since most of my photo dimensions are multiples of eight; scaling by half, quarter etc.. seemed safest to preserve image aspect ratios.

--
Bruno

Donald Johnston

unread,
Jul 10, 2016, 10:22:28 PM7/10/16
to Hugin Pano
Bruno … I thought of the integers also so have been trying to modify the code to ensure calculated values are integers where required. However not being a perl expert I’ve run into an error I can’t understand.

Following some examples in your code I wrote:

    $i->{w} = int ($i->{w} *= $R);
    $i->{h} = int ($i->{h} *= $R);
    $i->{d} = int ($i->{d} *= $R if $i->{d} =~ /^[-0-9.]+$/);
    $i->{e} = int ($i->{e} *= $R if $i->{e} =~ /^[-0-9.]+$/);
    $i->{Vx} = int ($i->{Vx} *= $R if $i->{Vx} =~ /^[-0-9.]+$/);
    $i->{Vy} = int ($i->{Vy} *= $R if $i->{Vy} =~ /^[-0-9.]+$/);

The first two lines seem to work but then I get an error (I think the third line above is line 34) as follows:

syntax error at /Applications/Panotools-Script-0.28/bin/ptoscale line 34, near "$R if"
Global symbol "$i" requires explicit package name at /Applications/Panotools-Script-0.28/bin/ptoscale line 35.
Global symbol "$i" requires explicit package name at /Applications/Panotools-Script-0.28/bin/ptoscale line 35.
syntax error at /Applications/Panotools-Script-0.28/bin/ptoscale line 35, near "$R if"
Global symbol "$i" requires explicit package name at /Applications/Panotools-Script-0.28/bin/ptoscale line 35.


Also, if d, e, Vx, and Vy are pixel values why are you even doing the match in those lines???

Any suggestions would help. 



--
A list of frequently asked questions is available at: http://wiki.panotools.org/Hugin_FAQ
---
You received this message because you are subscribed to the Google Groups "hugin and other free panoramic software" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hugin-ptx+...@googlegroups.com.

Bruno Postle

unread,
Jul 11, 2016, 4:10:14 AM7/11/16
to hugi...@googlegroups.com


On 11 July 2016 03:22:28 BST, Donald Johnston wrote:

>Following some examples in your code I wrote:

>> $i->{d} = int ($i->{d} *= $R if $i->{d} =~ /^[-0-9.]+$/);

Misplaced brackets, something like:

int ($i->{d} *= $R) if ...

(writing on my phone, so excuse me for not typing the whole line!)

>The first two lines seem to work but then I get an error (I think the
>third line above is line 34)
>
>Also, if d, e, Vx, and Vy are pixel values why are you even doing the
>match in those lines???

I have no idea, mistakes are always a possibility.

--
Bruno

Bruno Postle

unread,
Jul 11, 2016, 5:23:16 AM7/11/16
to hugi...@googlegroups.com
On 11 July 2016 03:22:28 BST, Donald Johnston wrote:

>Following some examples in your code I wrote:

>> $i->{d} = int ($i->{d} *= $R if $i->{d} =~ /^[-0-9.]+$/);

Misplaced brackets, something like:

int ($i->{d} *= $R) if ...

(writing on my phone, so excuse me for not typing the whole line!)

>The first two lines seem to work but then I get an error (I think the
>third line above is line 34)
>
>Also, if d, e, Vx, and Vy are pixel values why are you even doing the
>match in those lines???

Donald Johnston

unread,
Jul 22, 2016, 5:14:59 PM7/22/16
to Hugin Pano
Attached below is what I think is a working copy of the ptoscale Perl module.

If anyone has a chance can you test it out and let me know if you have any problems.
It works in conjunction with and requires Bruno’s Panotools:: Script Perl module

On Jul 11, 2016, at 3:22 AM, Bruno Postle <br...@postle.net> wrote:

On 11 July 2016 03:22:28 BST, Donald Johnston wrote:

>Following some examples in your code I wrote:

>> $i->{d} = int ($i->{d} *= $R if $i->{d} =~ /^[-0-9.]+$/);

Misplaced brackets, something like:

int ($i->{d} *= $R) if …

(writing on my phone, so excuse me for not typing the whole line!)

Thanks Bruno. I can see why the Perl compiler might have problems with an “if” statement as an argument for the “int” function.


>The first two lines seem to work but then I get an error (I think the
>third line above is line 34)
>
>Also, if d, e, Vx, and Vy are pixel values why are you even doing the
>match in those lines???

I have no idea, mistakes are always a possibility.

Never “mistakes”; best to refer to them as “features”.  I’ve just left them in the modified code for ptoscale.


--
Bruno


Some notes on the code.
  1. I had to move the code that handles the crop (S) from the image lines to the $p->Panorama line. Is this something you would have to do with your ptohalf and ptodouble modules?
  2. Is there a web page that details the format of the lines within a .pto file? I’ve done a search but haven’t been able to find anything.
  3. The int function doesn’t work well with floating point numbers so I turned it into more of a rounding function by adding 0.5 to the values before doing the integer. Sometimes what Perl might display as 4913 for example is actually 4912.9999999999 in floating point and so int returns 4912.
  4. I wrote an extensive help part for the module (I hope it is understandable).
  5. To be quite honest I have no idea what some of the lines in the code do as this is my first attempt at Perl (Thanks for your help Bruno!!!)

One test I did (below) was because I had made the small trial .pto project at 1600 pixels before I realized I’d want to scale back up to the large image size at 7360 pixels.

/Applications/Panotools-Script-0.28/bin/ptoscale -s 7360/1600 -o scaled.pto trial.pto




THE CODE


#!/usr/bin/perl
use strict;
use warnings;
use Panotools::Script;
use Getopt::Long;
use Pod::Usage;

my $scale;
my $path_output;
my $help = 0;

GetOptions ('s|scale=s' => \$scale,
            'o|output=s' => \$path_output,
            'h|help' => \$help);

pod2usage (-verbose => 2) if $help;

my $path_pto = shift || pod2usage;
die "Can't find $path_pto" unless -e $path_pto;

my $R = 1;
if ($scale =~ /\//)
{
    my @Ratio = split ('/', $scale);
    $R = $Ratio[0] / $Ratio[1];
} else {
    $R=$scale
}

my $p = new Panotools::Script;
$p->Read ($path_pto);

$p->Panorama->{w} = int (0.5 + ($p->Panorama->{w} *= $R));
$p->Panorama->{h} = int (0.5 + ($p->Panorama->{h} *= $R));
if (defined $p->Panorama->{S})
{
    my @S = split (',', $p->Panorama->{S});
    @S = map {int (0.5 + ($_ * $R))} @S;
    $p->Panorama->{S} = join ',', @S;
}

for my $i (@{$p->Image})
{
    $i->{w} = int (0.5 + ($i->{w} *= $R));
    $i->{h} = int (0.5 + ($i->{h} *= $R));
    $i->{d} = int (0.5 + ($i->{d} *= $R)) if $i->{d} =~ /^[-0-9.]+$/;
    $i->{e} = int (0.5 + ($i->{e} *= $R)) if $i->{e} =~ /^[-0-9.]+$/;
    $i->{Vx} = int (0.5 + ($i->{Vx} *= $R)) if $i->{Vx} =~ /^[-0-9.]+$/;
    $i->{Vy} = int (0.5 + ($i->{Vy} *= $R)) if $i->{Vy} =~ /^[-0-9.]+$/;
}

for my $c (@{$p->Control})
{
    $c->{x} *= $R;
    $c->{y} *= $R;
    $c->{X} *= $R;
    $c->{Y} *= $R;
}

for my $k (@{$p->Mask})
{
    my $string = $k->{p};
    $string =~ s/"//g;
    my @p = split (' ', $string);
    @p = map {int (0.5 + ($_ * $R))} @p;
    $k->{p} = '"'. (join ' ', @p) .'"';
}

$p->Write ($path_output);

exit 0;

__END__

=head1 NAME

ptoscale - rescale a panorama project

=head1 SYNOPSIS

ptoscale [options] --output scaled.pto project.pto

 Options:
  -s | --scale      Scale ratio (in the format n; or m/n where m = new side length, n = old side length)
  -o | --output     Filename of scaled project (can be the same as the input)
  -h | --help       Outputs help documentation

=head1 DESCRIPTION

B<ptoscale> takes a hugin .pto project and scales all pixel dimensions by the ratio given (--scale).  It is best to use a scale factor consisting of the common divisors of the width and height of the image (in pixels).

For example: an image that is 3648x2736 has common divisors of 2, 2, 2, 2, and 3. So a scale factor of 4, 6, or 8 would work (also 3648/912, 3648/608, or 3648/456). Inverses and rationals work also: 0.5, 1.5, and 2/3 for example.

You will need to rescale the photos to match:

  mogrify -geometry {m/n}% *.JPG

Note, this tool is useful in conjunction with the L<ptodouble> and L<ptohalve> tools which
perform the specific scaling of 2 and 0.5 respectively.

=head1 TYPICAL WORKFLOW

1. Create lower resolution copies of your image so you can experiment with hugin settings (this will reduce computation time for testing). Use a reduction amount similar to the scale factor covered above.

for example: convert 3648x2736 images to 608x456 pixels (a scale factor of 6)

2. When you're please with the results use ptoscale to modify your pto file to work with your original images.

ptoscale -s 3648/608 -o scaled.pto trial.pto

ptoscale -s 6 -o scaled.pto trial.pto
Reply all
Reply to author
Forward
0 new messages