3

I'd like to outline an object in a transparent background with a 20px border. But, I want to fill in the closed regions with the border color.

$image = new Imagick('./img/hinata.png');
$mask = clone $image;
$mask->separateImageChannel(Imagick::CHANNEL_ALPHA);
$mask->negateImage(true);
$mask->edgeImage(20);
$mask->opaquePaintImage("white","blue",65000,false);
//// TODO: I don't know how to fill the holes
$mask->transparentPaintImage("black",0.0,0,false);
$image->compositeImage($mask,Imagick::COMPOSITE_DEFAULT,0,0);

I referenced this question: Outline a transparent image using imagick PHP

This is the image: enter image description here

This is what I want to achieve: enter image description here

This is not what I want to achieve: enter image description here

fmw42
  • 46,825
  • 10
  • 62
  • 80
tomorin
  • 157
  • 1
  • 6
  • Please post your original input, not one that has checkerboard in place of transparency. Extract the alpha channel, then use morphology dilate to extend it. Then use connected components to fill the holes. – fmw42 Aug 26 '19 at 16:47

1 Answers1

2

This is how I would do it in ImageMagick command line.

Make the background under the transparency blue.

Extract the alpha channel.

Dilate the alpha channel.

Use connected components to fill in any "holes" smaller than some threshold in area.

Replace the old alpha channel with the new one


Input: from here

enter image description here

convert cartoon_girl.png -background blue -alpha background \
\( -clone 0 -alpha extract \
-morphology dilate diamond:12 \
-define connected-components:mean-color=true \
-define connected-components:area-threshold=500 \
-connected-components 8 \) \
-alpha off -compose copy_opacity -composite \
result.png


enter image description here

Unfortunately, Imagick does not support connected components as far as I know. So the only other way would be to use flood fill at some point inside each "hole". That means you have to pick x,y coordinate inside each hole to use for doing the flood fill after doing the dilate. See https://www.php.net/manual/en/imagick.floodfillpaintimage.php

convert cartoon_girl.png -background blue -alpha background \
\( -clone 0 -alpha extract \
-morphology dilate diamond:12 \
-fuzz 80% -fill white \
-draw "color 100,310 floodfill" \
-draw "color 200,235 floodfill" -alpha off  \) \
-alpha off -compose copy_opacity -composite \
result2.png


enter image description here

fmw42
  • 46,825
  • 10
  • 62
  • 80
  • It's very helpful! FloodFill is the very method that I was looking for. I found it in PHP and the method is `Imagick::floodFillPaintImage()`. If I can specify the coordinates of the center of the holes, I'll be able to fill them in, I guess. Thank you! – tomorin Aug 27 '19 at 07:00
  • Yes, the link to Imagick::floodFillPaintImage() was already in my answer. – fmw42 Aug 27 '19 at 16:55