How can I get the co-ordinates of the convex hull of a piece of Text?
Asked
Active
Viewed 1,244 times
17
Emre
- 1,720
- 2
- 13
- 21
-
2Anyone would have a method that doesn’t first rasterize the text? – F'x Apr 01 '12 at 18:13
4 Answers
21
An alternative approach that does not require the ComputationalGeometry package: You can use a combination of ClusteringComponents and ComponentMeasurements as follows:
Define
chVertices[txtimg_] :=
Insert[#, First@#, -1] &@
ComponentMeasurements[ClusteringComponents[Binarize@txtimg, 2],
"ConvexVertices"][[2, 2]]
Example data:
textimg1 = Image[Graphics[
Text[Style["'., ab cgixyz,...", Green, FontFamily -> "Times", FontSize -> 72]]],
ImageSize -> {600, 100}];
textimg2 = Image[Graphics[{EdgeForm[], Brown,
ImportString[ExportString[
Style[".t e q s t,", Italic, FontFamily -> "Times", FontSize -> 36],
"PDF"], "PDF", "TextMode" -> "Outlines"][[1, 1]]}], ImageSize -> {600, 100}];
textimg3 = Image[Graphics[
Text[Style["Get Convex Hull points.", Orange, 56]]],
ImageSize -> {600, 100}];
Input pictures:

Results:
Row[Show[#, Graphics@{Red, Thick, Line[chVertices[#]]}] &
/@ {textimg1, textimg2, textimg3}]

kglr
- 394,356
- 18
- 477
- 896
15
The question could be rephrased: how do we get a vector graphic from a bitmap? The solution is pretty simple by using the code we can find here.
p = Image[Graphics[Text[Style["Get Convex Hull points.", Large]]]];
img = Thinning@EdgeDetect@p;
points = N@Position[ImageData[img], 1];
pts = Union@Flatten[FindCurvePath[points] /. c_Integer :> points[[c]], 1];
Needs["ComputationalGeometry`"]
chp = ConvexHull[pts];
Show[
Graphics@{Red, Thick, Line[Append[pts[[chp]], pts[[chp]][[1]]]]},
ListPlot[pts]]

11
Another method:
text = Rasterize["Text"];
data = Position[text[[1, 1]], {0, 0, 0}];
rotated = RotationMatrix[90 Degree].# & /@ data;
data2D = {-#1, #2} & @@@ rotated;
<< ComputationalGeometry`
Quiet[convexhull = ConvexHull[data2D]];
hull = PlanarGraphPlot[data2D, convexhull];
Graphics[{Black, Point[data2D], hull[[1, 2]]}]

Working it a bit more:
t = Text[Style["Text", FontFamily -> "Times", FontSize -> 48]];
text = Rasterize[t, ImageResolution -> 80];
data = Position[text[[1, 1]], Table[Except@255, {3}]];
rotated = RotationMatrix[90 Degree].# & /@ data;
data2D = {-#1, #2} & @@@ rotated;
<< ComputationalGeometry`
Quiet[convexhull = ConvexHull[data2D]];
hull = PlanarGraphPlot[data2D, convexhull];
Graphics[{Black, Point[data2D], hull[[1, 2]]}]

{{xmin, xmax}, {ymin, ymax}} = {Min@#, Max@#} & /@ Transpose[data2D];
Graphics[{Black,
Inset[text, {xmin + (xmax - xmin)/2 - 1, ymin + (ymax - ymin)/2},
Center, Reverse@Most[Dimensions[text[[1, 1]]]]],
Red, hull[[1, 2]]},
PlotRange -> {{xmin - 3, xmax + 3}, {ymin - 3, ymax + 3}}]

Chris Degnen
- 30,927
- 2
- 54
- 108
9
In Version 10, this can be elegantly done in one line. First we create some text (stealing from @kguler) as follows:
img = Image[Graphics[Text[Style["'., ab cgixyz,...", Green, FontFamily -> "Times",
FontSize -> 72]]], ImageSize -> {600, 100}];
Then:
cvx = ConvexHullMesh @ ImageValuePositions[EdgeDetect[img, 3], White];
Visualize:
Show[img, Graphics[GraphicsComplex[MeshCoordinates[cvx], {Thick, Red, MeshCells[cvx, 1]}]]]

RunnyKine
- 33,088
- 3
- 109
- 176