5
$\begingroup$

I intend to optimize my work by adding an outline to my images automatically.

I'm leaving this image as a reference for testing:

enter image description here

I can make an outline of the image, but with poor quality ...

ColorNegate[EdgeDetect[AlphaChannel[Import["https://i.sstatic.net/PvtRV.png"]],2,0.07,Method->"Canny"]]

I intend to achieve this result by combining the original image with the outline:

enter image description here

$\endgroup$
1
  • $\begingroup$ See this related question and answer (195840) where Dilation can thicken the EdgeDetect result. $\endgroup$
    – flinty
    Commented Oct 8, 2020 at 23:00

2 Answers 2

5
$\begingroup$
thickness = 10;
img = Import["https://i.sstatic.net/PvtRV.png"];

1. ContourDetect + EdgeDetect + Dilation

ImageMultiply[img, ColorNegate @
  Dilation[EdgeDetect @ ImagePad[ColorNegate @ ContourDetect[img], 20], thickness]]

enter image description here

2. ComponentMeasurements

img0 = ImagePad[img, 10]; 

Show[img0, Graphics[{AbsoluteThickness[thickness], Red, 
   MaximalBy[Length @* First] @
    First[Values[ComponentMeasurements[img0, "Contours"]]]}]]

enter image description here

$\endgroup$
1
  • $\begingroup$ This code with leaked images worked better $\endgroup$
    – LCarvalho
    Commented Oct 8, 2020 at 23:18
3
$\begingroup$

Using ImageMesh and textures is a little more awkward than I expected it to be, but it does the job without needing image manipulation like EdgeDetect:

img = ImageCrop[Import["https://i.sstatic.net/PvtRV.png"]];
mesh = ImageMesh[AlphaChannel[img]];
coords = MeshCoordinates[mesh];
mmx = MinMax[coords[[All, 1]]];
mmy = MinMax[coords[[All, 2]]];
texcoords = {Rescale[#[[1]], mmx], Rescale[#[[2]], mmy]} & /@ coords;
g = Graphics[{Thickness[.05], Line[coords], Texture[img], 
  Polygon[coords, VertexTextureCoordinates -> texcoords]}]

with border

Hopefully the result is satisfactory. You can now rasterize it out using r = Rasterize[g, RasterSize -> ImageDimensions[img]]. However you may notice it no longer lines up with the original if you do ImageCompose[img,{r,0.5}]. That is due to some irritating quirk of ImageMesh and I have not figured out a work around yet.


Here's how I managed it using image processing functions:

ImageCompose[
 img, (* t controls the thickness *)
 With[{t = 5, dims = ImageDimensions[img]},
  Antialiasing ColorConvert[
    ColorNegate@
     ImageResize[
      ColorReplace[
       Dilation[EdgeDetect@ImagePad[AlphaChannel@img, t], t], 
       Black -> Transparent], dims], "RGB"]
  ]
 ]

image padding

$\endgroup$
4
  • $\begingroup$ For the intended purpose, I believe it can meet my need $\endgroup$
    – LCarvalho
    Commented Oct 8, 2020 at 23:08
  • $\begingroup$ Hollow objects do not produce good results. I just tested ... $\endgroup$
    – LCarvalho
    Commented Oct 8, 2020 at 23:16
  • $\begingroup$ You didn't specify that in the question or give a hollow image example. In any case the EdgeDetect one will work, not the textured Polygon. $\endgroup$
    – flinty
    Commented Oct 8, 2020 at 23:43
  • $\begingroup$ Sorry ... After I went to test that I realized the possibilities $\endgroup$
    – LCarvalho
    Commented Oct 8, 2020 at 23:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.