# Measure the length and width of the image

I obtained the images from a Magneto Optic Kerr Effect system from which I have to do some calculations. I cannot calculate the desired information from the images. The details are as follows: From the image I have to calculate the length and width of the black part of the image (which can be assumed to be a rectangle). So, I first use the command for finding the radius and threshold of the image and then convert it into a binary image. The command I use is

Manipulate[EdgeDetect[image, r, t], {{r, 2, "radius"}, 1, 10},
{{t, 0.1, "threshold"}, 0, 0.5}]


And then I get this result after detecting the edges of the black rectangle. Now I have to calculate the width and the length at several different positions in the black box and then take the average to get the mean result. As I know that I will definitely get the result in pixels which I can then convert to real world measurements using the scale bar, but I am unable to calculate the length and the width.

Since I am new to Mathematica as well as image processing, help will be highly appreciated.

img = Import["http://i.stack.imgur.com/eYXlo.jpg"];
(* clean the image and binarize it: *)
imgClean = img // Blur[#, 2] & // Binarize // ColorNegate // Erosion[#, 2] &;
(* Fit the boundingbox and extract the corners: *)
cornerCoords = MorphologicalTransform[imgClean, "BoundingBoxes", ∞] //
ImageCorners[#, MaxFeatures -> 4] &


{{66.5, 57.5}, {66.5, 155.5}, {196.5, 57.5}, {196.5, 155.5}}

HighlightImage[img, cornerCoords] So we have the size of the rectangle:

{-1, 1}.cornerCoords[[{1, -1}]]


{130., 98.}

## Edit:

As ImageCorners is introduced in version 9, in case you're using elder version, here is another way to extract the boundingbox. (There are of course many ways, e.g. CornerFilter, to do this or just extrating the corners. Also note I do not have a version 8, the following code is supposed to work under v8 according to the documentation.)

boundingbox = CrossingDetect[LaplacianGaussianFilter[
MorphologicalTransform[imgClean, "BoundingBoxes", ∞],
2], CornerNeighbors -> True]

boundaryCoords = ImageData[boundingbox] // Reverse[#]\[Transpose] & // Position[#, 1] &;

Graphics[{Darker[Green], Thickness[.01], Dashed,
Line[#[[FindCurvePath[#][]]] &@boundaryCoords]
}] // Show[{boundingbox, #}] & • Indeed the information was very helpful. Now, I see that if I calculate the length and width of the image using only one value, then it might be not so accurate. So, I am trying to extract the coordinates of the box after binarizing. However, the GET Coordinates option is giving some errors when I try to manually select the points and get the coordinates. Is there any way to just get the ccordinates of the bounding box which bounds the black area of the image?
– Sam
Dec 22, 2013 at 7:26
• By the way I use Mathematica 8, so please keep in mind that I cannot use Pixel value Positions command for the work....
– Sam
Dec 22, 2013 at 7:39
• @Sam Please see my edit. I'm not sure it will work under v8, but the documentation says the functions involved are all ready in 8. Dec 22, 2013 at 8:36

Let's start with your image and do a bit of image processing to clean it up:

img = Import["http://i.stack.imgur.com/eYXlo.jpg"];
clean = Dilation[Erosion[MorphologicalBinarize[ColorNegate[img]], 2], 3] Now we can use ComponentMeasurements to find out about the two components (in this case, the black and the white). For example, the area of the white is:

ComponentMeasurements[clean, "Area"]
{1 -> 13893.4}


Since you are interested in the perimeter, you might choose the option:

ComponentMeasurements[clean, "BoundingBox"]
{1 -> {{62., 53.}, {201., 160.}}}


which gives the coordinates of the bounding box (actually the lower left and upper right coordinates of the bounding box). There are many other kinds of information you can extract using ComponentMeasurements.

Following your edge detection, image data is extracted as rows of mostly 0's and some 1's for the edge:

i1 = Import@"http://i.stack.imgur.com/eYXlo.jpg";
i2 = EdgeDetect[i1, 8.7, .08];
data = ImageData[i2];


This scans every row and returns the difference (dimension) if exactly two white pixels are found in it. After reaping the return values, mean is calculated.

dim[data_] :=
N@Mean[Reap[
Do[
With[{p = Position[row, 1]},
If[Length[p] == 2,
Sow[Abs[Subtract @@ Flatten[p]]]]],
{row, data}]
][[2, 1]]]


Applying to rows and columns:

dim /@ {data, Transpose@data}
{131.725, 102.042}


I think taking the mean length of the horizontal and vertical black lines in the binarized image is better than just calculating some feature of the bounding box or the corners:

i = Import["http://i.stack.imgur.com/eYXlo.jpg"];
i1 = Opening[Binarize@Closing[i, 3], 2]
p1 = Position[ImageData[i1], 0];
f[n_]:= N@Mean[(Max@#-Min@#)&/@ Map[#[[3-n]]&, Select[GatherBy[p1, #[[n]] &], Length@# > 70 &], {2}]]
{f, f}
(*
{127.59, 99.4803}
*)