A year late, but here are my thoughts:

As Szabolcs showed, extracting the `Line`

primitives from a `RegionPlot`

provides a convenient way to produce a polygon from an image. The function `imgToPolys`

below does just that - it's essentially the same as Szabolcs' code but I use `ImageValue`

instead of creating an interpolating function from the image data.

Of course, some of the polygons produced this way are the "holes" in letters. In order to display the text properly we need to identify which polygons are holes and which are "solids" (for want of a better word). The function `findHoles`

takes a list of polygons and uses the undocumented function `Graphics`Mesh`InPolygonQ`

to test whether the first point of each polygon lies inside any of the other polygons. I've assumed that any "holes" are completely contained within a surrounding "solid", so that testing a single point is sufficient. The expression returned by `findHoles`

is a list of {solids, holes}.

```
imgToPolys[img_Image] :=
Module[{w, h, rp},
{w, h} = ImageDimensions[img];
rp = RegionPlot[
ImageValue[img, {x, y}] < 0.5, {x, 0.5, w - 0.5}, {y, 0.5, h - 0.5},
PlotPoints -> 100];
Cases[Normal[rp], l_Line :> Polygon @@ l, -1]];
findHoles[p : {_Polygon ..}] := Module[{inq, holes, solids},
inq = Outer[Graphics`Mesh`InPolygonQ, p, p[[All, 1, 1]], 1];
holes = DeleteCases[inq ~Position~ True , {x_, x_}][[All, 2]];
solids = Complement[Range[Length[p]], holes];
{p[[solids]], p[[holes]]}];
```

Here's an example where I have shown the holes in white, so they look like, well, holes.

```
input = Style["{##}&/@", Bold, FontFamily -> "Calibri", FontSize -> 12];
img = Rasterize[input, ImageSize -> 800] ~ColorConvert~ "Grayscale" ~
ImageResize~ 400;
{solids, holes} = findHoles@imgToPolys@img;
Graphics[{EdgeForm[Red], Yellow, solids, White, holes}]
```

## Faster method using FilledCurve

The procedure above is rather slow, due to the `RegionPlot`

. An alternative way to create polygons from text is from the `FilledCurve`

primitives that can be obtained by converting via PDF (as in Vitaliy's answer). Below is some code to convert the filled curves into polygons.

The conversion is a two stage process, first the filled curves are converted to bezier curves, then the bezier curves are sampled at some number of points (default 10), and the coordinates fed into a `Polygon`

expression.

As previously, the polygons can then be split into "solids" and "holes" using `findHoles`

.

```
filledCurveToBeziers[fc_FilledCurve] := MapThread[processFCdata, List @@ fc];
processFCdata[desc_, pts_] := Module[{r, sd},
r = Range @@@
ReplacePart[
Partition[Prepend[Accumulate[desc[[All, 2]]], 0], 2, 1], {1, 1} -> 1];
sd = desc[[All, 3]] /. {0 -> 1};
MapThread[BezierCurve[pts[[#1]], SplineDegree -> #2] &, {r, sd}]];
beziersToPolygons[x_, n_: 10] :=
Module[{samples},
samples = x /. BezierCurve[data__] :> BezierFunction[data] /@ Range[0, 1, 1/n];
Polygon /@ Select[Split[Flatten[#, 1]][[All, 1]] & /@ samples, Length[#] > 1 &]];
```

This approach is much faster, since it completely avoids the rasterization and image processing.

```
{solids, holes} =
With[{fc = Cases[ImportString[ExportString[input, "PDF"]], _FilledCurve, -1]},
Transpose[findHoles@beziersToPolygons[filledCurveToBeziers@#, 10] & /@ fc]];
Graphics[{EdgeForm[Red], Yellow, solids, White, holes}]
```

See http://forums.wolfram.com/mathgroup/archive/2011/Mar/msg00529.html

– Daniel Lichtblau – 2012-01-24T22:25:02.6802You can also use

`EdgeDetect`

for detecting the edges – rm -rf – 2012-01-24T22:49:21.563@R.M. I tried that, but at first sight the gradient filter looked slightly better to me. The other one looked a bit more irregular. However, the edge detected version has a smaller set of points and that's actually good (question 2) – Sjoerd C. de Vries – 2012-01-24T23:09:23.470

1

`FindCurvePath`

(or`ListCurvePathPlot`

) or`FindShortestTour`

with one of its many`Method`

option values (`"Greedy"`

?) could be of use. I don't have time to figure out a full solution now. – Szabolcs – 2012-01-24T23:24:48.713A relevant question from SO. Sadly Graham scans work only for convex polygons, but you can use it if the outline for the character is convex. – J. M.'s ennui – 2012-01-25T00:10:46.577

1

Related: 75855

– shrx – 2015-04-16T20:12:16.053