I am trying to detect and characterize the size, orientation, and centroid of nearly perfect hexagonal features in images. The built-in MorphologicalComponents commands do not seem to DIRECTLY provide the needed functionality (unless I am missing something).

I have coded the following but I am looking for a simpler method. My current methodology is to EdgeDetect followed by detection of the hexagon's side by ImageLines and then to reconstitute the hexagon suitable for MorphologicalComponents to process.

img = Import["https://i.sstatic.net/QxbKv.png"];
hex = ColorConvert[img, "Grayscale"];
GraphicsRow[{img, hex}, ImageSize -> Large]
{col, row} = ImageDimensions[img];
edg = EdgeDetect[GaussianFilter[hex, 2], Method -> {"Canny"}] //  DeleteSmallComponents[#, 500] &
lines = ImageLines[edg, .04, MaxFeatures -> 6];
p0 = Graphics[{Thickness[.01], Orange, lines}];
p1 = Show[edg, p0];
p2 = Show[hex, p0];
GraphicsRow[{p1, p2}, ImageSize -> Large]
Show[MorphologicalComponents[p0 /. Orange -> Black] // Colorize]
ComponentMeasurements[p0 /. Orange -> Black, {"Area", "Centroid"}]

trail image

  • $\begingroup$ What is imag in your code? $\endgroup$
    – Eisbär
    Commented Oct 7, 2022 at 6:33

1 Answer 1


ComponentMeasurements has a lot of interesting and useful measures. To select a hexagon, you can use, for example, the combination of "Circularity" (which can be calculated exactly1 for a hexagon) and "Elongation" (which should be zero for a hexagon). Then, you can use "ConvexVertices" to get the points of a convex hull. The convex hull will almost always more than 6 vertices. To get a hexagon orientation, calculate the largest distance from the centroid to the vertices. Alternatively, you can also use "MinimalBoundingBox" to get the orientation.

Obviously, you can make the code more robust. Also, the last step can be replaced with some kind of "hexagon fitting" to the points. The choice of method depends on your actual aims of the task.

bin = Binarize[hex];
comps = DeleteSmallComponents[MorphologicalComponents[bin], 50];

c = Sqrt[\[Pi]]/(Sqrt[2] 3^(1/4));
ceps = 0.1;
eeps = 0.05;

hexagon = SelectComponents[comps, 
            (c - ceps < #Circularity < c + ceps) && (#Elongation < eeps) &];

{pts, center} = First@Values@ComponentMeasurements[hexagon, {"ConvexVertices", "Centroid"}];

vertex = First@MaximalBy[pts, EuclideanDistance[center, #] &];

mbb = First@Values@ComponentMeasurements[hexagon, "MinimalBoundingBox"];

Show[hex, Graphics[{Red, Thick, Line[{center, vertex}]}], 
 Graphics[{EdgeForm[Green], Transparent, Polygon[mbb]}]]


1 Circularity is defined as $2 \pi r/p$, with polygonal length $p$ and equivalent disk radius $r$. A hexagon with a side length $a$ has area $(3\sqrt{3}/2)a^2$. Calculating the radius of an equivalent disk: $\pi r^2 = (3\sqrt{3}/2)a^2 \implies r=3^{3/4}a/(2\pi)$, from which the cirularity can be calculated as $c=2\pi r/(6a) = \sqrt{\pi/(2 \sqrt{3})}$.

  • $\begingroup$ Very helpful thanks $\endgroup$
    – OpticsMan
    Commented Oct 17, 2022 at 15:14

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.