Go Back   CodingForums.com > :: Server side development > PHP

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 03-11-2010, 08:19 PM   PM User | #1
Macmee
New to the CF scene

 
Join Date: Oct 2008
Posts: 5
Thanks: 2
Thanked 0 Times in 0 Posts
Macmee is an unknown quantity at this point
PHP script to match images doesn't work

For example, I might have an image here:


And I might be looking for the smaller image:


within that bigger image. I want to get the x,y coordinates to where that image is in the large one. Here's the source code I have to do this:

PHP Code:
<?php
//small image
$im2 ImageCreateFromPNG("SMALL IMAGE.png");
$width imagesx($im2);
$height imagesy($im2);
$size2 $width $height;
$cw 0;
$ch 0;
$image2 "|";
for(
$i 0$i $size2$i++)
{
    
$image2 .= imagecolorat($im2$cw$ch)."|";
    if(
$cw == ($width 1))
    {
        
$cw 0;
        
$ch++;
    }else{
        
$cw++;
    }
}



//large image
$im ImageCreateFromPNG("BIG IMAGE.png");
$width imagesx($im);
$height imagesy($im);
$size2 $width $height;
$cw 0;
$ch 0;
$image "";

for(
$i 0$i $size2$i++)
{
    
$image .= imagecolorat($im$cw$ch)."|";
    if(
$cw == ($width 1))
    {
        
$cw 0;
        
$ch++;
    }else{
        
$cw++;
    }
}


//finding position of patch in strings
$find explode($image2,$image);
$coordinate substr_count($find[0], '|');


//converting position from string to x y coordinates
$width imagesx($im);
$check $coordinate $width;
$check explode(".",$check);
$y $check[0] + 1;
$x $coordinate $width;
if((
$coordinate $width) == 0)
{
    
$x $width;
    
$y--;
}


//printing result
echo "x: {$x}<br>y: {$y}";




?>
I tested each individual component of that manually and they all worked, but when put together it doesn't find the proper coordinates, just bogus ones. If someone could shed some light on this I would really appreciate it

Thank you,
Dave Z
Macmee is offline   Reply With Quote
Old 03-11-2010, 08:41 PM   PM User | #2
mlseim
Master Coder

 
mlseim's Avatar
 
Join Date: Jun 2003
Location: Cottage Grove, Minnesota
Posts: 9,055
Thanks: 8
Thanked 1,032 Times in 1,023 Posts
mlseim has a spectacular aura aboutmlseim has a spectacular aura aboutmlseim has a spectacular aura about
So you're saying that is compares every pixel in the small image to every pixel
in the large image to figure out where all of the pixels match?
mlseim is offline   Reply With Quote
Old 03-11-2010, 08:53 PM   PM User | #3
bacterozoid
Regular Coder

 
bacterozoid's Avatar
 
Join Date: Jun 2002
Location: USA
Posts: 489
Thanks: 24
Thanked 35 Times in 35 Posts
bacterozoid is an unknown quantity at this point
Dude, your algorithm needs some work. Instead of storing everything in a massive string like that and then using explode, try this:

Load up both your large and small images

Use a loop (two levels deep) to go through every pixel in your large image. If the pixel you are at in your large image matches the top left pixel of your small image, then step into a verify subroutine

The verify subroutine would then check the other pixels to see if they are a match. You could probably get away with checking a fairly low percentage of pixels - maybe check a grid with 10px in between each. This would depend on the desired size of your small image, but you should be able to get pretty good results (and much more efficiently)
bacterozoid is offline   Reply With Quote
Old 03-11-2010, 09:26 PM   PM User | #4
bacterozoid
Regular Coder

 
bacterozoid's Avatar
 
Join Date: Jun 2002
Location: USA
Posts: 489
Thanks: 24
Thanked 35 Times in 35 Posts
bacterozoid is an unknown quantity at this point
Because I thought the problem to be interesting and because you already tried yourself, here's one way to do it:

PHP Code:
<?php

// Large Image
$big ImageCreateFromPNG("big.png");
$big_w imagesx($big);
$big_h imagesy($big);

// Small Image
$small ImageCreateFromPNG("small.png");

// Loop over every pixel in the large image
for($cy 0$cy $big_h$cy++) { // This loops over vertically
    
for($cx 0$cx $big_w$cx++) { // This loops over horizontally
        
if(imagecolorat($big$cx$cy) == imagecolorat($small00)) { // See if the current pixel in the large image matches the top left pixel in the small one
            
if(verify($cx$cy$big$small)) { // If there is a potential match, verify if it is a full match
                
die("X=$cx, Y=$cy"); // If it is a full match, stop doing work and output the result
            
}
        }
    }
}
echo 
"Not Found"// No match found

// Check and see if the given cx, cy position is a match
function verify($cx$cy, &$big, &$small) { // The & passes by reference...basically just saves you memory
    
$small_w imagesx($small);
    
$small_h imagesy($small);
    
    
// Use the threshhold to prevent checking every single pixel. It can be assumed that if you
    // have a spaced out grid of matches, you are pretty close
    
$threshhold 20;
    for(
$sy 0$sy $small_h$sy+=$threshhold) {
        for(
$sx 0$sx $small_w$sx+=$threshhold) {
            if(
imagecolorat($small$sx$sy) != imagecolorat($big$cx $sx$cy $sy)) {
                return 
false;
            }
        }
    }
    return 
true;
}

?>
bacterozoid is offline   Reply With Quote
Users who have thanked bacterozoid for this post:
Macmee (03-16-2010)
Old 03-12-2010, 12:47 AM   PM User | #5
Macmee
New to the CF scene

 
Join Date: Oct 2008
Posts: 5
Thanks: 2
Thanked 0 Times in 0 Posts
Macmee is an unknown quantity at this point
Quote:
Originally Posted by bacterozoid View Post
Because I thought the problem to be interesting and because you already tried yourself, here's one way to do it:

PHP Code:
<?php

// Large Image
$big ImageCreateFromPNG("big.png");
$big_w imagesx($big);
$big_h imagesy($big);

// Small Image
$small ImageCreateFromPNG("small.png");

// Loop over every pixel in the large image
for($cy 0$cy $big_h$cy++) { // This loops over vertically
    
for($cx 0$cx $big_w$cx++) { // This loops over horizontally
        
if(imagecolorat($big$cx$cy) == imagecolorat($small00)) { // See if the current pixel in the large image matches the top left pixel in the small one
            
if(verify($cx$cy$big$small)) { // If there is a potential match, verify if it is a full match
                
die("X=$cx, Y=$cy"); // If it is a full match, stop doing work and output the result
            
}
        }
    }
}
echo 
"Not Found"// No match found

// Check and see if the given cx, cy position is a match
function verify($cx$cy, &$big, &$small) { // The & passes by reference...basically just saves you memory
    
$small_w imagesx($small);
    
$small_h imagesy($small);
    
    
// Use the threshhold to prevent checking every single pixel. It can be assumed that if you
    // have a spaced out grid of matches, you are pretty close
    
$threshhold 20;
    for(
$sy 0$sy $small_h$sy+=$threshhold) {
        for(
$sx 0$sx $small_w$sx+=$threshhold) {
            if(
imagecolorat($small$sx$sy) != imagecolorat($big$cx $sx$cy $sy)) {
                return 
false;
            }
        }
    }
    return 
true;
}

?>
That works beautifully, thank you The only part I don't understand is in your for statement in the verify function where you put +=

Quote:
Originally Posted by bacterozoid View Post
Dude, your algorithm needs some work. Instead of storing everything in a massive string like that and then using explode, try this:

Load up both your large and small images

Use a loop (two levels deep) to go through every pixel in your large image. If the pixel you are at in your large image matches the top left pixel of your small image, then step into a verify subroutine

The verify subroutine would then check the other pixels to see if they are a match. You could probably get away with checking a fairly low percentage of pixels - maybe check a grid with 10px in between each. This would depend on the desired size of your small image, but you should be able to get pretty good results (and much more efficiently)
Thanks, I never thought of doing it like that
Macmee is offline   Reply With Quote
Old 03-12-2010, 12:52 AM   PM User | #6
mlseim
Master Coder

 
mlseim's Avatar
 
Join Date: Jun 2003
Location: Cottage Grove, Minnesota
Posts: 9,055
Thanks: 8
Thanked 1,032 Times in 1,023 Posts
mlseim has a spectacular aura aboutmlseim has a spectacular aura aboutmlseim has a spectacular aura about
This:
$sy += $threshhold;

Is shorthand for this:
$sy = $sy + $threshhold;
mlseim is offline   Reply With Quote
Old 03-12-2010, 01:04 AM   PM User | #7
Macmee
New to the CF scene

 
Join Date: Oct 2008
Posts: 5
Thanks: 2
Thanked 0 Times in 0 Posts
Macmee is an unknown quantity at this point
Quote:
Originally Posted by mlseim View Post
This:
$sy += $threshhold;

Is shorthand for this:
$sy = $sy + $threshhold;
Ooh ok. So when it's verifying it's actually moving 20 pixels across and 20 pixels down to continue each pixel check?
Macmee is offline   Reply With Quote
Old 03-12-2010, 03:18 AM   PM User | #8
bacterozoid
Regular Coder

 
bacterozoid's Avatar
 
Join Date: Jun 2002
Location: USA
Posts: 489
Thanks: 24
Thanked 35 Times in 35 Posts
bacterozoid is an unknown quantity at this point
Yep. This way you're not checking every single pixel - your script will complete quicker and use less resources.

Skipping every 20px (at least on an image this size) should generally be good enough to detect a match, as the likliehood of that happening anywhere else in the image is pretty low. If you have problems, just decrease that threshold value.
bacterozoid is offline   Reply With Quote
Reply

Bookmarks

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 10:26 AM.


Advertisement
Log in to turn off these ads.