How to measure the slit size from given image using mathematica?
Extract lines at the edge of the object:
img = Import["https://i.stack.imgur.com/pT8aP.jpg"]
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 = Internal`ListMin[pc][[All, 2]];
lm2 = -Internal`ListMin[-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 *)