Php 使用imagemagick确定图像是否为黑白

Php 使用imagemagick确定图像是否为黑白,php,image,image-processing,imagemagick,Php,Image,Image Processing,Imagemagick,我有一个图像目录,我需要分为彩色和黑白。使用image magik getImageType很容易检测到这一点。然而,有些图像被认为是黑白的,但有一些黄色阴影 是否有一种已知的方法来查看某些值并确定其在技术上仍然是黑白的 计算为黑白但返回为真彩色的图像: 剧本 <?php $dir = getcwd(); $dirToImages = getcwd().'/imagesToScan/'; $files = scandir($dirToImages); $badFiles = array(

我有一个图像目录,我需要分为彩色和黑白。使用image magik getImageType很容易检测到这一点。然而,有些图像被认为是黑白的,但有一些黄色阴影

是否有一种已知的方法来查看某些值并确定其在技术上仍然是黑白的

计算为黑白但返回为真彩色的图像:

剧本

<?php

$dir = getcwd();
$dirToImages = getcwd().'/imagesToScan/';
$files = scandir($dirToImages);
$badFiles = array('.DS_Store', '.', '..', 'index.php', 'bAndW', 'color');
@mkdir('colour');
@mkdir('bAndW');
echo "\n\n starting script, counting images: \n\n";
echo "image count: ".count($files)."  \n\n ";

foreach($files as $file) {
    /* if the file is shit, its not an image, skip it */
    if (in_array($file, $badFiles)) {
        continue;
    }
    /* directories or bad files don't have an extension, fool proof */
    $exploded = explode('.', $file);
    if (!isset($exploded[1])) {
        continue;
    }
    echo $file;
    /* okay do the work */
    $imagick_type = new Imagick();
    $file_to_grab = $dirToImages.'/'.$file;
    $file_handle_for_viewing_image_file = fopen($file_to_grab, 'a+');
    $imagick_type->readImageFile($file_handle_for_viewing_image_file);
    $image_type = $imagick_type->getImageType();

    switch($image_type)
    {
        case imagick::IMGTYPE_UNDEFINED:
            $image_type_title = "Undefined";
            break;

        case imagick::IMGTYPE_BILEVEL:
            $image_type_title = "Bilevel";
            break;

        case imagick::IMGTYPE_GRAYSCALE:
            $image_type_title = "Grayscale";
            break;

        case imagick::IMGTYPE_GRAYSCALEMATTE:
            $image_type_title = "Grayscale Matte";
            break;

        case imagick::IMGTYPE_PALETTE:
            $image_type_title = "Palette";
            break;

        case imagick::IMGTYPE_PALETTEMATTE:
            $image_type_title = "Palette Matte";
            break;

        case imagick::IMGTYPE_TRUECOLOR:
            $image_type_title = "Truecolor";
            break;

        case imagick::IMGTYPE_TRUECOLORMATTE:
            $image_type_title = "Truecolor Matte";
            break;

        case imagick::IMGTYPE_COLORSEPARATION:
            $image_type_title = "Color Separation";
            break;

        case imagick::IMGTYPE_COLORSEPARATIONMATTE:
            $image_type_title = "Color Separation Matte";
            break;

        case imagick::IMGTYPE_OPTIMIZE:
            $image_type_title = "Optimize";
            break;
    }

    if ($image_type == 2) {
//        copy($dirToImages.'/'.$file, $dir.'/bAndW/'.$file);
    } else {
//        copy($dirToImages.'/'.$file, $dir.'/colour/'.$file);
    }
    echo $file."
    \n Filename: ".$image_type.":
    \n Type: ".$image_type_title ."
    \n reddPrimary: ".print_r($imagick_type->getImageRedPrimary(),true)."
    \n getImageBackgroundColor: ".print_r($imagick_type->getImageBackgroundColor(),true)."
    \n ColourSpace: ".print_r($imagick_type->getColorspace(),true)."
    \n\n ";

}

也许有更好的方法,但通过查看Imagick的文档,看起来是这样的。也许您可以使用以下内容:

$im=new Imagick( 'image.png' );
$iterator=$im->getPixelIterator();

// Tracks whether the image is black and white or not.
$b_and_w = true;

/* The tolerance value. This is how close the color of the pixel
 *must be to gray for it to count the image as black and white.
 */
$t = 5;

/* Check the value of every $x pixels. This is to allow the script
 * to run faster, but will lower the accuracy.
 */
$x = 2;

// Count of current pixel
$c = 0;

foreach( $iterator as $row => $pixels ) {
    foreach ( $pixels as $column => $pixel ){

        // If this pixel is not every $x pixel, skip it
        if(++$c % $x !== 0) continue;

        // Find unnormal color of pixel
        $color = $pixel->getColor();

        // Find average color of pixel
        $average = array_sum($color)/3;

        /* Compare the rgb values of this pixel to the average.
         * If any of them aren't close, that means it's not a shade of gray.
         */
        if(!in_array($color['r'],range(max(0,$average-$t),min(255,$average+$t)))
        || !in_array($color['g'],range(max(0,$average-$t),min(255,$average+$t)))
        || !in_array($color['b'],range(max(0,$average-$t),min(255,$average+$t)))){

            // Set our boolean to false
            $b_and_w = false;

            // Now we abandon the loops
            break 2;
        }
    }
}

if($b_and_w) echo "This image is black and white";
else         echo "This image has at least one pixel that's colored";
它会将每个
$x
像素的颜色与每个像素的平均颜色(黑色和白色)进行比较。如果出现它们不够接近的情况,循环将退出,
$b_和_w
将设置为false。如果未找到彩色像素,
$b_和_w
将保持为真


请记住,我还没有测试过这一点,所以这可能需要在您这方面做一些工作。祝你好运。

除了迭代每个像素以检查灰度与否之外,你还可以通过以下步骤找到黑白图像

  • 将图像的颜色空间转换为HSL
  • 了解绿色通道的平均值
  • 如果为零,则为黑白图像,否则不是
希望这对你有帮助


谢谢

将克隆的灰度图像与原始图像进行比较?不确定在php thoughNice建议中会是什么样子,但是我发布的图片的颜色计数会因为黄色而变得很高。@azz0r不幸的是,我必须去工作,所以我不能修改我的脚本。但是,黄色是蓝色和绿色的,因此在比较之前,您可以尝试反转
g
b
值。类似于
abs(255-$color['g'])
的东西应该可以反转颜色。如果这仍然不起作用,请尝试不比较b和g颜色值,只检查红色。@azz0r我的错误,黄色是g和r,而不是g和b。试着做我上面提到的,除了只检查蓝色值。这个解决方案在理论上应该是可行的,但在实践中,它会为对象中的图像输出类似“0.176712”的值。不确定什么是阈值来考虑图像的“灰度”最好的方法
$im=new Imagick( 'image.png' );
$iterator=$im->getPixelIterator();

// Tracks whether the image is black and white or not.
$b_and_w = true;

/* The tolerance value. This is how close the color of the pixel
 *must be to gray for it to count the image as black and white.
 */
$t = 5;

/* Check the value of every $x pixels. This is to allow the script
 * to run faster, but will lower the accuracy.
 */
$x = 2;

// Count of current pixel
$c = 0;

foreach( $iterator as $row => $pixels ) {
    foreach ( $pixels as $column => $pixel ){

        // If this pixel is not every $x pixel, skip it
        if(++$c % $x !== 0) continue;

        // Find unnormal color of pixel
        $color = $pixel->getColor();

        // Find average color of pixel
        $average = array_sum($color)/3;

        /* Compare the rgb values of this pixel to the average.
         * If any of them aren't close, that means it's not a shade of gray.
         */
        if(!in_array($color['r'],range(max(0,$average-$t),min(255,$average+$t)))
        || !in_array($color['g'],range(max(0,$average-$t),min(255,$average+$t)))
        || !in_array($color['b'],range(max(0,$average-$t),min(255,$average+$t)))){

            // Set our boolean to false
            $b_and_w = false;

            // Now we abandon the loops
            break 2;
        }
    }
}

if($b_and_w) echo "This image is black and white";
else         echo "This image has at least one pixel that's colored";