How to measure the slit size from given image using mathematica?

I want to measure the size of the optical slit from the microscope image.

Here is the image:

The dimension of image data is $1300\times1030$ and the real pixel size is $6.7$ micron.

But the problem is the slit in this image is tilted.

How can I measure width of the slit from this image?

• Welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Take the tour! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! – Michael E2 May 5 '16 at 14:44
• Rotate the image. – David G. Stork May 5 '16 at 15:20
• mathematica.stackexchange.com/questions/86396/… – Karsten 7. May 5 '16 at 16:20
• Although the answers linked by @Karsten can also answer this question, I think this one's still distinct because it doesn't focus on the variation in slit width. This simplification makes it possible to get results with a simpler approach, which I point out in my answer. It would also apply to the other question, but would require more work to characterize the variations. – Jens May 5 '16 at 19:41

Extract lines at the edge of the object:

lines = ImageLines[EdgeDetect[FillingTransform[Binarize[img]]]];
HighlightImage[img, {Thick, Yellow, Line /@ lines}]


From here you can rotate the image if you get the angle:

θ = Mean[ArcTan @@@ Subtract @@@ lines]
(* 1.67222 *)

ImageTransformation[img, RotationTransform[\[Theta] - Pi/2],
Padding -> 0, PlotRange -> All]


and from here proceed how you would have if it wasn't tilted.

On the other hand, you can try the following as well. Here I take random points from one of the lines and find the minimum distance to the other line. I then take the mean of all of these minimum distances.

pts = RandomPoint[Line[lines[[2]]], 500];
Mean[RegionDistance[Line[lines[[1]]]] /@ pts]
(* 83.175 *)


in microns:

Mean[RegionDistance[Line[lines[[1]]]] /@ pts]*Quantity[6.7, "Microns"]
(* Quantity[556.521, "Microns"] *)


Here is an approach that requires no manual interaction:

g = Import["http://i.stack.imgur.com/pT8aP.jpg"];

shape = Position[ImageData[Binarize[g]], 1, {2}];
pc = PrincipalComponents[N@shape];
lm1 = InternalListMin[pc][[All, 2]];
lm2 = -InternalListMin[-pc][[All, 2]];

slitWidth = Mean[lm2] - Mean[lm1]

(* ==> 83.6331 *)


Here, I'm using the undocumented function ListMin from Daniel's answer here after first doing the image rotation automatically using PrincipalComponents as I also did here.

To see how this works, look at the points collected in PrincipalComponents:

ListPlot[pc, AspectRatio -> Automatic, PlotRange -> All]


The points making up the slit have been aligned so that we now only have to determine a measure of the vertical extent. This is what I do with ListMin.

Of course, you can now convert to physical units by multiplying the pixel count with the micron ratio:

6.7 slitWidth

(* ==> 560.342 *)