#!/usr/bin/perl # Ronit Slyper, October 2007 # Program to register an image (here, with itself) by displaying it in a canvas and allowing clicking. # Loads/Saves files "input_points.txt" and "base_points.txt" # This program is nice because it numbers points in each image separately; so you can click on a few points in one image, # then go over to the other and click those same corresponding points in order. # Use "pop" repeatedly to remove the highest numbered points. # Use the entry widget to enter the number of a point you want to adjust, then click the LRUD direction buttons to move it # (I realize this is inconvenient; it's a hack because the Tk::Canvas key bindings aren't working for me.) # load the file in to whatever scaled size is easiest to work with; set xscale and yscale and picture_height, below. use Tk; @ip_x; @ip_y; @ip_id; @bp_x; @bp_y; @bp_id; # the image we're loading is scaled by 2 from the actual image (because, to keep this program simple, it doesn't do any zooming). # points are stored scaled, but are scaled back down when output (and scaled up when read in) $xscale = 2; $yscale = 2; $picture_height = 231; # set this! $mw = MainWindow->new(); $frame = $mw->Frame(); $frame->Button(-text => "load", -command => \&loadpts)->pack(-side => "top"); $frame->Button(-text => "save", -command => \&savepts)->pack(-side => "top"); $frame->Button(-text => "pop1", -command => \&im1_pop)->pack(-side => "top"); $frame->Button(-text => "pop2", -command => \&im2_pop)->pack(-side => "top"); $move_pt_number = 0; $frame->Entry(-textvariable => \$move_pt_number, -width => 5)->pack(-side => "top"); $frame->Button(-text => "1L", -command => [\&move_ip, -3, 0])->pack(-side => "top"); $frame->Button(-text => "1U", -command => [\&move_ip, 0, -3])->pack(-side => "top"); $frame->Button(-text => "1D", -command => [\&move_ip, 0, 3])->pack(-side => "top"); $frame->Button(-text => "1R", -command => [\&move_ip, 3, 0])->pack(-side => "top"); $frame->Button(-text => "2L", -command => [\&move_bp, -3, 0])->pack(-side => "top"); $frame->Button(-text => "2U", -command => [\&move_bp, 0, -3])->pack(-side => "top"); $frame->Button(-text => "2D", -command => [\&move_bp, 0, 3])->pack(-side => "top"); $frame->Button(-text => "2R", -command => [\&move_bp, 3, 0])->pack(-side => "top"); $frame->pack(-side => "left"); $canvas = $mw->Canvas(-width => 996*$xscale, -height => 462*$yscale); $canvas->pack(); $imgptr = $mw->Photo(-file => "LW446D.bmp"); $im1 = $canvas->createImage(0,0,-image => $imgptr, -anchor => "nw", -tags => "im1"); $im2 = $canvas->createImage(0,$yscale * $picture_height,-image => $imgptr, -anchor => "nw", -tags => "im2"); $canvas->bind($im1, "", [ \&im1_pressed, Ev('x'), Ev('y') ]); $canvas->bind($im2, "", [ \&im2_pressed, Ev('x'), Ev('y') ]); loadpts(); sub move_ip { print "move_ip\n"; ($dx, $dy) = @_; $number = $move_pt_number; if ($number < 0 || $number >= scalar(@ip_x)) { return; } print "Moving item # $number\n"; $ip_x[$number] += $dx; $ip_y[$number] += $dy; $canvas->move($ip_text[$number], $dx, $dy); $canvas->move($ip_id[$number], $dx, $dy); } sub move_bp { print "move_bp\n"; ($dx, $dy) = @_; $number = $move_pt_number; if ($number < 0 || $number >= scalar(@bp_x)) { return; } print "Moving item # $number\n"; $bp_x[$number] += $dx; $bp_y[$number] += $dy; $canvas->move($bp_text[$number], $dx, $dy); $canvas->move($bp_id[$number], $dx, $dy); } sub im1_pop { print "Pop 1!\n"; pop @ip_x; pop @ip_y; $id = pop @ip_id; $text = pop @ip_text; $canvas->delete($id, $text); } sub im2_pop { print "Pop 2!\n"; pop @bp_x; pop @bp_y; $id = pop @bp_id; $text = pop @bp_text; $canvas->delete($id, $text); } sub im1_pressed { @a = @_; print "Im1 pressed. Coords: " . $a[1] . " " . $a[2] . "\n"; ($id, $textid) = add_disp_pt(1, $a[1], $a[2], "" . scalar(@ip_x)); push @ip_x, ( $a[1] ); push @ip_y, ( $a[2] ); push @ip_id, ( $id ); push @ip_text, ( $textid ); } sub im2_pressed { @a = @_; print "Im2 pressed. Coords: " . $a[1] . " " . $a[2] . "\n"; $a[2] -= $picture_height * $yscale; ($id, $textid) = add_disp_pt(2, $a[1], $a[2], "" . scalar(@bp_x)); push @bp_x, ( $a[1] ); push @bp_y, ( $a[2] ); push @bp_id, ( $id ); push @bp_text, ( $textid ); } sub add_disp_pt { ($imnum, $x, $y, $number) = @_; $cs = 2; if ($imnum==1) { $centerx = $x; $centery = $y; $fill = "blue"; } elsif ($imnum==2) { $centerx = $x; $centery = $y + $picture_height * $yscale; $fill = "red"; } else { print "Huh? Who's adding a point??\n"; } $id = $canvas->createOval($centerx - $cs, $centery - $cs, $centerx + $cs, $centery + $cs, -fill => $fill, -tags => "circ"); $textid = $canvas->createText($centerx - $cs, $centery - $cs, -anchor => "sw", -text => $number, -fill => "red"); return ($id, $textid); } sub loadpts { print "Loading.\n"; @ip_x = (); @ip_y = (); @ip_id = (); @ip_text = (); @bp_x = (); @bp_y = (); @bp_id = (); @bp_text = (); open(INIP, "input_points.txt"); $n = 0; while ($line = ) { chomp $line; $line =~ /^\s*(\S+)\s+(\S+)\s*$/; push @ip_x, ( $1*$xscale ); push @ip_y, ( $2*$yscale ); ($id, $textid) = add_disp_pt(1, $1*$xscale, $2*$yscale, $n); $n++; push @ip_id, ($id); push @ip_text, ($textid); } close OUTIP; open(INBP, "base_points.txt"); $n = 0; while ($line = ) { chomp $line; $line =~ /^\s*(\S+)\s+(\S+)\s*$/; push @bp_x, ( $1*$xscale ); push @bp_y, ( $2*$yscale ); ($id, $textid) = add_disp_pt(2, $1*$xscale, $2*$yscale, $n); $n++; push @bp_id, ($id); push @bp_text, ($textid); } close OUTBP; print "Points loaded:\n"; print "Input " . scalar(@ip_x) . "\n"; print "Base " . scalar(@bp_x) . "\n"; print "which equals $n each\n"; print "Number 64: $ip_x[64] $ip_y[64] $bp_x[64] $bp_y[64]\n\n"; } sub savepts { print "Saving.\n"; print "Number of points being saved:\n"; print "Input " . scalar(@ip_x) . "\n"; print "Base " . scalar(@bp_x) . "\n"; print "Number 64: $ip_x[64] $ip_y[64] $bp_x[64] $bp_y[64]\n\n"; open(OUTIP, ">input_points.txt"); for $i (0..(scalar(@ip_x) - 1)) { print OUTIP "\t" . $ip_x[$i]/$xscale . "\t" . $ip_y[$i]/$yscale . "\n"; } close OUTIP; open(OUTBP, ">base_points.txt"); for $i (0..(scalar(@bp_x) - 1)) { print OUTBP "\t" . $bp_x[$i]/$xscale . "\t" . $bp_y[$i]/$yscale . "\n"; } close OUTBP; } MainLoop();