使用Imagick PHP轮廓透明图像

14

我有一张带透明背景的图片,想要用5像素的边框勾勒出来。在 Photoshop 中,我可以使用描边功能实现。

我尝试使用borderImage,但它无法勾勒企鹅。

$image = new Imagick();
$image->readImage('tux.png');

$image->borderImage(new ImagickPixel('red'), 5, 5); // no outline

这是图片。

tux original

这是我想要实现的效果。

tux outlined


形态学相关的内容在这里有一个例子:http://phpimagick.com/Imagick/morphology?morphologyType=14 - Danack
2个回答

11
我将从命令行开始,可能稍后会涉及到PHP,或者让你自己解决这一部分...
步骤1 - 提取透明度
正如您所看到的,-border描绘了整个图像,但实际上您只想描绘不透明的区域,因此需要处理透明度或alpha层。首先让我们提取它:
convert tux.png -alpha extract alpha.png

enter image description here

第二步 - 获取不透明区域的边缘

现在,您想要该轮廓的边缘,因此我将使用 -morphology

convert alpha.png -morphology edge octagon -threshold 50% edge.png

enter image description here

我听说一些人在PHP中使用形态学操作时遇到了困难,因此这里提供了一种不使用形态学的替代方法。基本上,它会复制alpha层,然后使用统计学方法找到每个3x3框中最亮的像素(仅在存在黑色和白色像素的3x3框边缘才会产生影响),然后将结果与原始结果进行差异以显示受影响的像素。比描述起来更容易实现!

convert alpha.png \( +clone -statistic maximum 3x3 -threshold 50% \) -compose difference -composite edge.png

在此输入图片描述

对于更粗的线,请使用5x5的盒子。

我看到有一个选项-edge 5,这样会更容易 - 我们不断学习进步!

步骤3 - 将边缘变成红色,其余透明

现在您需要将白色变为红色,将黑色变为透明:

convert edge.png -fill red -opaque white -transparent black rededge.png

这里输入图片描述

第四步 - 在原图上添加红色轮廓

最后,您需要将其与原始图像合成:

convert tux.png rededge.png -composite result.png

在此输入图像描述

全面实现

或者,您可以像这样一次性完成所有操作:

convert tux.png  \( +clone -alpha extract -morphology edge octagon -threshold 50% -fill red -opaque white -transparent black \) -composite result.png

您可能更喜欢使用 -morphology edgeout 命令,因为它的效果比 -morphology edge 更加微妙。

PHP 版本

我的 PHP 技能 "较弱",但我已经开始学习并取得了一些进展——稍后会更新,目前看起来是这样的:

   $image = new Imagick("tux.png");
   $alpha = clone $image;
   $alpha->separateImageChannel(Imagick::CHANNEL_ALPHA);
   $alpha->negateImage(true);
   $alpha->edgeImage(5);
   $alpha->opaquePaintImage("white","red",65000,FALSE);
   $alpha->transparentPaintImage("black",0.0,0,FALSE);
   $image->compositeImage($alpha,Imagick::COMPOSITE_DEFAULT,0,0);
   $image->writeImage("result.png");

看起来这基本上是有效的,但有些方面可能需要整理 - 特别是 65000 这个神奇的数字和可能存在的一些不必要的克隆等等 - 我会把这留给你来处理!


太棒了!我一直在尝试用PHP复制它,但一直没有成功。你能把它转换成PHP吗? - steve
我尝试过一些业余的PHP - 我会让你将其提升到生产质量的水平 :-) - Mark Setchell
太棒了,马克!我很感激。如果需要,请随意更新它。 - steve
1
第三步不起作用 - 我得到了一个空的输出图像 :/ - Nico S.
1
你能把轮廓线画得多细? - Shmack

0

输入图像描述 函数getCharacterOutline() {

$imagick = new \Imagick(realpath("pen.png"));
$character = new \Imagick();
$character->newPseudoImage(
    $imagick->getImageWidth(),
    $imagick->getImageHeight(),
    "canvas:white"
);
$canvas = new \Imagick();
$canvas->newPseudoImage(
    $imagick->getImageWidth(),
    $imagick->getImageHeight(),
    "canvas:black"
);

$character->compositeimage(
    $imagick,
    \Imagick::COMPOSITE_COPYOPACITY,
    0, 0
);
$canvas->compositeimage(
    $character,
    \Imagick::COMPOSITE_ATOP,
    0, 0
);
$canvas->setFormat('png');

return $canvas;

}

$canvas = getCharacterOutline();
$kernel   =\ImagickKernel::fromBuiltIn(\Imagick::KERNEL_OCTAGON, "3");
$canvas->morphology(\Imagick::MORPHOLOGY_EDGE, 1, $kernel);
header("Content-Type: image/png"); 
echo $canvas->getImageBlob();
 [result][1]

你能把轮廓线画得多细? - Shmack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接