【发布时间】:2021-07-29 08:14:39
【问题描述】:
有没有办法结合这两个代码和结果来创造完美的东西?另外,我想细化PNG文件的轮廓,使其更美观。
原始文件:
代码 1: 当我需要从实心图像中移除背景(无需移除其中的区域)时,此代码非常有效
<?php
// input_file
$input_file = "100001.jpg";
// $output_file
$output_file = "100001.png";
// Load the image
$imagick = new Imagick(realpath($input_file));
// We replace white background with fuchsia to improve clipping
$imagick->floodFillPaintImage("rgb(255, 0, 255)", 2500, "rgb(255,255,255)", 0 , 0, false);
// We convert fuchsia to transparent
$imagick->paintTransparentImage("rgb(255,0,255)", 0, 10);
// We eliminate empty areas to only leave objects
$imagick->trimImage(0);
// Maximum 500 height but the width can exceed 500 if the original image exceeds 500 somewhere
$imagick->resizeImage(0, 500, Imagick::FILTER_CATROM, 1);
// We scale to a maximum of 500 width or height, take the largest measurement and lower it to 500
$imagick->scaleImage(500, 500, true);
// We export as PNG
$imagick->setImageFormat('png');
// Path to save new image
$imagick->writeImage($output_file);
// We clean cache
$imagick->clear();
// We destroy everything
$imagick->destroy();
?>
输出文件 1:(在这种情况下,软管内部没有被移除)
代码 2: 移除软管内的背景是正确的做法
<?php
// input_file
$input_file = "100001.jpg";
// $output_file
$output_file = "100001.png";
// Load the image
$imagick = new Imagick(realpath($input_file));
$backgroundColor = "rgb(255, 255, 255)";
$fuzzFactor = 0.1;
// Create a copy of the image, and paint all the pixels that
// are the background color to be transparent
$outlineImagick = clone $imagick;
$outlineImagick->transparentPaintImage($backgroundColor, 0, $fuzzFactor * Imagick::getQuantum(), false);
// Copy the input image
$mask = clone $imagick;
// Deactivate the alpha channel if the image has one, as later in the process
// we want the mask alpha to be copied from the colour channel to the src
// alpha channel. If the mask image has an alpha channel, it would be copied
// from that instead of from the colour channel.
$mask->setImageAlphaChannel(Imagick::ALPHACHANNEL_DEACTIVATE);
//Convert to gray scale to make life simpler
$mask->transformImageColorSpace(Imagick::COLORSPACE_GRAY);
// DstOut does a "cookie-cutter" it leaves the shape remaining after the
// outlineImagick image, is cut out of the mask.
$mask->compositeImage($outlineImagick,Imagick::COMPOSITE_DSTOUT, 0, 0);
// The mask is now black where the objects are in the image and white
// where the background is.
// Negate the image, to have white where the objects are and black for
// the background
$mask->negateImage(false);
$fillPixelHoles = false;
if ($fillPixelHoles == true) {
// If your image has pixel sized holes in it, you will want to fill them
// in. This will however also make any acute corners in the image not be
// transparent.
// Fill holes - any black pixel that is surrounded by white will become
// white
$mask->blurimage(2, 1);
$mask->whiteThresholdImage("rgb(10, 10, 10)");
// Thinning - because the previous step made the outline thicker, we
// attempt to make it thinner by an equivalent amount.
$mask->blurimage(2, 1);
$mask->blackThresholdImage("rgb(255, 255, 255)");
}
//Soften the edge of the mask to prevent jaggies on the outline.
$mask->blurimage(2, 2);
// We want the mask to go from full opaque to fully transparent quite quickly to
// avoid having too many semi-transparent pixels. sigmoidalContrastImage does this
// for us. Values to use were determined empirically.
$contrast = 15;
$midpoint = 0.7 * Imagick::getQuantum();
$mask->sigmoidalContrastImage(true, $contrast, $midpoint);
// Copy the mask into the opacity channel of the original image.
// You are probably done here if you just want the background removed.
$imagick->compositeimage($mask,Imagick::COMPOSITE_COPYOPACITY, 0, 0);
// Copy the image with the background removed over it.
$imagick->compositeimage($imagick, Imagick::COMPOSITE_OVER, 0, 0);
// We eliminate empty areas to only leave objects
$imagick->trimImage(0);
// Maximum 500 height but the width can exceed 500 if the original image exceeds 500 somewhere
$imagick->resizeImage(0, 500, Imagick::FILTER_CATROM, 1);
// We export as PNG
$imagick->setImageFormat('png');
// Path to save new image
$imagick->writeImage($output_file);
// We clean cache
$imagick->clear();
// We destroy everything
$imagick->destroy();
?>
输出文件2:如果你注意的话,它也会擦除风扇内部的标志,甚至在右上方的螺丝上(见最后添加的绿色背景图片)
添加了带有绿色背景的图像以发现问题
输出文件 1: 不移除软管内的背景。
输出文件2:错误,去掉TT风扇标志和右上角风扇螺丝
【问题讨论】:
-
我已经很好地为您寻找了,Imagick 似乎没有办法忽略小区域而只透明填充较大的区域。它只是不知道什么是背景,什么是图像的一部分。
-
自动执行此操作几乎是不可能的,背景的定义会有所不同,并且会有些错误
-
输出是有道理的,风扇标志有一些与白色背景相似的白色像素,这只能手动解决,对于不是完全白色但在黑白之间过渡的边缘也是如此
-
还有一种叫做压缩的东西,如果你要去除背景,你最好把你的初始图像设置为 png 而不是 jpg...如果你很好奇为什么然后 google png vs jpg
标签: php image-processing imagick