如何使用PHP在类似大小的图像之间进行图像差异?

时间:2013-11-23 08:16:10

标签: php ruby image image-processing

我刚刚发现了这篇文章http://jeffkreeftmeijer.com/2011/comparing-images-and-creating-image-diffs/

它正在讨论使用常规Ruby和ChunkyPNG来进行图像差异。

特别是第一个循环遍历所有像素的代码。

require 'chunky_png'

images = [
  ChunkyPNG::Image.from_file('1.png'),
  ChunkyPNG::Image.from_file('2.png')
]

diff = []

images.first.height.times do |y|
  images.first.row(y).each_with_index do |pixel, x|
    diff << [x,y] unless pixel == images.last[x,y]
  end
end

puts "pixels (total):     #{images.first.pixels.length}"
puts "pixels changed:     #{diff.length}"
puts "pixels changed (%): #{(diff.length.to_f / images.first.pixels.length) * 100}%"

x, y = diff.map{ |xy| xy[0] }, diff.map{ |xy| xy[1] }

images.last.rect(x.min, y.min, x.max, y.max, ChunkyPNG::Color.rgb(0,255,0))
images.last.save('diff.png')

我想知道

a)ChunkyPNG的理想PHP等价物是什么? b)PHP中相同代码的实现是什么?

1 个答案:

答案 0 :(得分:0)

你可以使用Imagick扩展程序。 Imagick是一个使用ImageMagick API创建和修改图像的本机php扩展。

使用Imagick :: compareImages()的示例:

比较图像并显示重建的图像。

<?php

$image1 = new imagick("image1.png");
$image2 = new imagick("image2.png");

$result = $image1->compareImages($image2, Imagick::METRIC_MEANSQUAREERROR);
$result[0]->setImageFormat("png");

header("Content-Type: image/png");
echo $result[0];

?>

OR

一个PHP shell脚本,通过逐个像素地比较它们来告诉您两个图像是否在视觉上不同。如果存在差异,脚本将创建第三个图像 - 黑色背景,其中不同的像素为绿色。这里两个GD图像是从输入文件创建的,也是第三个带有黑色背景的GD图像来存储diff。遍历所有像素并逐一进行比较。如果不同,请在差异图像的相同位置写入绿色像素。 [来源:http://www.phpied.com/image-diff/]

diff.php

<?php
/**
 * Shell script to tell if two images are identical.
 * If not, a third image is written - black background with the different pixels painted green
 * Code partially inspired by and borrowed from http://pear.php.net/Image_Text test cases
 */

// check if there's enough input
if (empty($argv[1]) || empty($argv[2])) {
    echo 'gimme at least two image filenames, please.', "\n";
    echo 'e.g. "php idiff.php img1.png img2.png"';
    echo "\n", 'third filename is the image diff, optional, default is "diffy.png"';
    exit(1);
}

// create images
$i1 = @imagecreatefromstring(file_get_contents($argv[1]));
$i2 = @imagecreatefromstring(file_get_contents($argv[2]));

// check if we were given garbage
if (!$i1) {
    echo $argv[1] . ' is not a valid image';
    exit(1);
}
if (!$i2) {
    echo $argv[2] . ' is not a valid image';
    exit(1);
}

// dimensions of the first image
$sx1 = imagesx($i1);
$sy1 = imagesy($i1);

// compare dimensions
if ($sx1 !== imagesx($i2) || $sy1 !== imagesy($i2)) {
    echo "The images are not even the same size";
    exit(1);
}

// create a diff image
$diffi = imagecreatetruecolor($sx1, $sy1);
$green = imagecolorallocate($diffi, 0, 255, 0);
imagefill($diffi, 0, 0, imagecolorallocate($diffi, 0, 0, 0));

// increment this counter when encountering a pixel diff
$different_pixels = 0;

// loop x and y
for ($x = 0; $x < $sx1; $x++) {
    for ($y = 0; $y < $sy1; $y++) {

        $rgb1 = imagecolorat($i1, $x, $y);
        $pix1 = imagecolorsforindex($i1, $rgb1);

        $rgb2 = imagecolorat($i2, $x, $y);
        $pix2 = imagecolorsforindex($i2, $rgb2);

        if ($pix1 !== $pix2) { // different pixel
            // increment and paint in the diff image
            $different_pixels++;
            imagesetpixel($diffi, $x, $y, $green);
        }

    }
}


if (!$different_pixels) {
    echo "Image is the same";
    exit(0);
} else {
    if (empty($argv[3])) {
        $argv[3] = 'diffy.png'; // default result filename
    }
    imagepng($diffi, $argv[3]);
    $total = $sx1 * $sy1;
    echo "$different_pixels/$total different pixels, or ", number_format(100 * $different_pixels / $total, 2), '%';
    exit(1);
}
?>

用法(命令行):

php diff.php img1.png img2.png result.png