#!/usr/bin/perl use strict; use warnings; use Image::Magick; use Data::Dumper; my $image='zahlenc.jpg'; my $offsetx=10; my $offsety=17; my $sx=17.26; my $sy=34.2; my @zahlen=( qw'5 9 7 4 0 3 2 6 5 8 4 6 1 2 3 5 8 7 9 8 0 1 2 4 5 8 9', qw'6 5 8 4 5 2 1 7 4 3 7 2 8 7 6 2 4 2 3 5 6 8 7 4 6 9 7', qw'0 2 6 3 8 9 7 5 6 4 9 7 5 4 4 3 0 2 1 5 8 5 4 1 0 5 5', qw'1 2 3 6 5 8 4 6 4 5 5 2 3 1 5 8 7 4 3 6 1 5 9 8 6 5 4', qw'3 2 7 4 6 9 1 0 2 8 9 4 5 6 2 2 5 9 7 6 0 2 9 7 0 0 4', qw'5 8 7 4 6 2 3 1 5 4 9 3 7 8 4 0 3 0 7 4 3 7 2 7 8 9 6', qw'8 4 5 6 2 4 8 5 0 7 3 6 1 8 7 4 5 6 2 1 2 9 6 7 4 5 1', qw'4 9 7 2 0 3 4 7 5 8 2 1 5 7 4 8 7 6 2 3 4 5 1 2 4 8 6', qw'3 2 7 4 3 7 2 0 4 9 1 4 7 6 3 2 6 5 8 9 1 4 9 7 5 6 0' ); my $magick=Image::Magick->new(); $magick->Read($image); $magick->Set(magick=>'GRAY'); my @img_zahlen=init_zahlen($magick,$offsety,$sy,\@zahlen); read_zahlen($magick,\@img_zahlen,$offsetx,$offsety,$sx,$sy); exit(); ######################################################################## ######################################################################## sub init_zahlen { my $magick=shift; my $offsety=shift; my $sy=shift; my $zahlen=shift(); my $show=$magick->clone(); my @data=(); my ($width,$height)=$magick->Get('width','height'); my @points=map{$_/255}unpack("C*",($magick->ImageToBlob(magick=>'GRAY'))[-1]); my $count=0; for (my $y=int($offsety)+int($sy/2); $y<$height; $y+=int($sy)) { my $x=0; for $x (0..$width-1) { if(defined($points[$y*$width+$x]) && $points[$y*$width+$x]<0.5) { my ($minx,$miny,$maxx,$maxy)=find_bbox($x,$y,$width,$height,\@points); my $img=$magick->clone(); $img->Crop(width=>$maxx-$minx+1, height=>$maxy-$miny+1, x=>$minx, y=>$miny); $img->Set(page => ($maxx-$minx+1).'x'.($maxy-$miny+1).'+0+0'); # fix offset Problem my $z=$zahlen->[$count]; push(@{$data[$z]},$img); $count++; #$show->Draw(primitive=>'line', points=>"0,$y , $width,$y", strokewidth=>1, stroke=>'black'); $show->Draw(primitive=>'rectangle', points=>"$minx,$miny , $maxx,$maxy", strokewidth=>1, stroke=>'black',fill=>'rgba(255, 255, 255, 0)'); $show->Draw(primitive=>'text', points=>"$minx,$miny '$z'", fill=>'black', pointsize=>'11', strokewidth=>1); } } } #$show->Display(); $show->Write('init_zahlen.png'); return @data; } sub read_zahlen { my $magick=shift; my $zahlen=shift; my $offsetx=shift; my $offsety=shift; my $sx=shift; my $sy=shift; my $show=$magick->Clone(); # Bild in Blöcke zerlegen und darin die Zahl suchen for(my $posx=$offsetx; ($magick->Get('width')-$posx) > $sx; $posx+=$sx) { for(my $posy=$offsety; ($magick->Get('height')-$posy) > $sy; $posy+=$sy) { my $img=$magick->Clone(); $img->Crop(width=>$sx, height=>$sy, x=>$posx, y=>$posy); $img->Set(page => $sx.'x'.$sy.'+0+0'); # fix offset Problem my ($zahl,$minx,$miny,$maxx,$maxy)=detect_zahl($img,$zahlen); $show->Draw(primitive=>'rectangle', points=>($minx+$posx).",".($miny+$posy).",".($maxx+$posx).",".($maxy+$posy), strokewidth=>1, stroke=>'black',fill=>'rgba(255, 255, 255, 0)'); $show->Draw(primitive=>'rectangle', points=>"$posx,$posy ".($posx+$sx).",".($posy+$sy), strokewidth=>1, stroke=>'black',fill=>'rgba(255, 255, 255, 0)'); $show->Draw(primitive=>'text', points=>($posx+2).",".($posy+$sy)." '$zahl'", fill=>'black', pointsize=>'11', strokewidth=>1); } } #$show->Display(); $show->Write('detect_zahlen.png'); } ######################################################################## ######################################################################## # unfassende Box für eine Zahl sub find_bbox { my ($x,$y,$width,$height,$points,$level)=@_; $level=0.9 unless(defined($level)); my ($mix,$miy,$max,$may)=($x,$y,$x,$y); my @list=([$x,$y]); while(@list > 0) { my ($px,$py)=@{shift(@list)}; next if($px<0 || $py<0 || $px >= $width || $py >= $height); next unless(defined($points->[$py*$width+$px])); my $c=$points->[$py*$width+$px]; $points->[$py*$width+$px]=undef; if($c < $level) { #print " POINT ($px,$py) FOUND\n"; $mix=$px if($mix>$px); $miy=$py if($miy>$py); $max=$px if($max<$px); $may=$py if($may<$py); push(@list,[$px-1,$py],[$px,$py-1],[$px+1,$py],[$px,$y+1]); push(@list,[$px-1,$py-1],[$px+1,$py-1],[$px-1,$py+1],[$px+1,$y+1]); } } return ($mix,$miy,$max+1,$may+1); } # Zahl erkennen sub detect_zahl { my $magick=shift; my $zahlen=shift; my ($width,$height)=$magick->Get('width','height'); $magick->Set(page => $width.'x'.$height.'+0+0'); # fix offset Problem # das Bild durch gehen my @points=map{$_/255}unpack("C*",($magick->ImageToBlob(magick=>'GRAY'))[-1]); for my $y (0..$height-1) { my $x=0; for $x (0..$width-1) { # wurde der punkt schon erkennt und ist er dunke genug? if(defined($points[$y*$width+$x]) && $points[$y*$width+$x]<0.5) { # finde die umschließende Box my ($minx,$miny,$maxx,$maxy)=find_bbox($x,$y,$width,$height,\@points); # ist die Box groß genug? if( ($maxx-$minx)*($maxy-$miny)*100/@points > 20 ) { my $w=$maxx-$minx; my $h=$maxy-$miny; my $zahl=-1; my $summ=undef; # den Inhalt auf Zahlen testen # Das Testbild vom gesuchten Bild abziehen # Das helste Bild muß es sein for my $cnt (0..$#$zahlen) { my $zahlimg=$zahlen->[$cnt]->[0]; my $img=$magick->clone(); $img->Crop(width=>$maxx-$minx, height=>$maxy-$miny, x=>$minx, y=>$miny); $img->Set(page => ($maxx-$minx).'x'.($maxy-$miny).'+0+0'); # fix offset Problem $img->Composite(compose=>'Divide', gravity=>'Center', image=>$zahlimg); my $insumm=0; $insumm+=($_/255) for(unpack("C*",($img->ImageToBlob(magick=>'GRAY'))[-1])); if(!defined($summ) || $insumm>$summ) { $summ=$insumm; $zahl=$cnt; } } return ($zahl,$minx,$miny,$maxx,$maxy) if($zahl != -1); } } } } return -1; }