Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Percentage of pixels that have changed in an image in PHP

Currently I have a single image from which I am retrieving a background color. I am making the background color transparent, then attempting to compare it to the original image to determine the percentage of the image that is comprised of said background color. Here is the code I am attempting to use:

$image = new Imagick($file);

// Make bg transparent for comparison
$tpImage = $image->clone();
$tpImage->setFormat('png');
$tpImage->setImagePage(0, 0, 0, 0);

$swatch_pixel = $tpImage->getImagePixelColor(1, 1);

$tpImage->paintTransparentImage($swatch_pixel, 0, 65535 * 0.1);

$image->SetOption('fuzz', '2%');
$result = $image->compareImages($tpImage, Imagick::METRIC_ABSOLUTEERRORMETRIC);

echo $result[0];

Currently this is always returning 0... I'm not sure if I need to use a different comparison method or what, or if I am doing something else wrong, I've spent quite some time on this and most of the resources I've found are pretty old.

like image 761
Mazzy Avatar asked Nov 09 '22 14:11

Mazzy


1 Answers

Updated Answer

Actually, now that you point it out explicitly, the ABSOLUTE_ERROR metric will not work when the only difference is transparency.

To answer your question, you probably just want to separate out the alpha channel using:

separateImageChannel(Imagick::CHANNEL_ALPHA);

and then get its statistical mean which will tell you what percentage of the pixels are white - i.e. transparent.

I'll leave the original answer below, because it is a useful technique that will work for any other image differencing that isn't purely about transparency.

Original Answer

You can get the image properties after the comparison and find the element called "distortion" in there. So, if I start with this image:

enter image description here

and then roll it right by 10 pixels:

enter image description here

<?php
   $image1 = new Imagick("image.png");
   $image2 = new Imagick("image.png");

   $result = $image1->compareImages($image2,Imagick::METRIC_MEANABSOLUTEERROR);
   $p1=$image1->getImageProperties();
   print_r($p1);
   $image1->rollImage(10,0);
   $result = $image1->compareImages($image2,Imagick::METRIC_MEANABSOLUTEERROR);
   $p1=$image1->getImageProperties();
   print_r($p1);
?>

Output

Array
(
    [date:create] => 2016-06-02T14:15:01+01:00
    [date:modify] => 2016-06-02T14:15:01+01:00
    [distortion] => 0                            <--- Here's the little devil
    [png:bKGD] => chunk was found (see Background color, above)
    [png:cHRM] => chunk was found (see Chromaticity, above)
    [png:gAMA] => gamma=0.45454544 (See Gamma, above)
    [png:IHDR.bit-depth-orig] => 4
    [png:IHDR.bit_depth] => 4
    [png:IHDR.color-type-orig] => 3
    [png:IHDR.color_type] => 3 (Indexed)
    [png:IHDR.interlace_method] => 0 (Not interlaced)
    [png:IHDR.width,height] => 200, 200
    [png:PLTE.number_colors] => 5
    [png:sRGB] => intent=0 (Perceptual Intent)
    [png:text] => 2 tEXt/zTXt/iTXt chunks were found
    [png:tIME] => 2016-06-02T14:15:01Z
)
Array
(
    [date:create] => 2016-06-02T14:15:01+01:00
    [date:modify] => 2016-06-02T14:15:01+01:00
    [distortion] => 0.0833333                     <--- Here's the little devil
    [png:bKGD] => chunk was found (see Background color, above)
    [png:cHRM] => chunk was found (see Chromaticity, above)
    [png:gAMA] => gamma=0.45454544 (See Gamma, above)
    [png:IHDR.bit-depth-orig] => 4
    [png:IHDR.bit_depth] => 4
    [png:IHDR.color-type-orig] => 3
    [png:IHDR.color_type] => 3 (Indexed)
    [png:IHDR.interlace_method] => 0 (Not interlaced)
    [png:IHDR.width,height] => 200, 200
    [png:PLTE.number_colors] => 5
    [png:sRGB] => intent=0 (Perceptual Intent)
    [png:text] => 2 tEXt/zTXt/iTXt chunks were found
    [png:tIME] => 2016-06-02T14:15:01Z
)
like image 123
Mark Setchell Avatar answered Nov 14 '22 23:11

Mark Setchell