-
Notifications
You must be signed in to change notification settings - Fork 0
/
Automatic-Size-Calculation.m
189 lines (135 loc) · 5.89 KB
/
Automatic-Size-Calculation.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
%% Image Processing for Materials Science Applications
% Automatic Size Calculation
% Written in Matlab R2013a
function ASC()
close all;
%Rescaling is required due to hardware limitations only
RescaleSize=0.8;
%Image resolution:
prompt = 'Please insert image resolution in nm:\n';
img_res=input(prompt); %nm
%Finds pixel to nm ratio
nm_per_plx = CalculateNMPerPLX(img_res,RescaleSize);
%A scale found from trial and error
%for background noise removal
SmallestObjectToRemove=-26*img_res+2033;
% A loop is created to allow different scan
% angles of the imclose function.
% a 20 degree scan from 0 to 180 has found
% to produce a proper result.
% 180 degrees scan is possible but requires
% additional computing time and will much
% necessarily produce a significantly different results.
counter=0;
for angleofScan=0:20:180
counter=counter+1;
%Collect Image and transform its histogram to grayscale
I = imread('Target.tif');
I = imresize(I,RescaleSize);
I= imcrop(I,[0 0 820 730]);
I = rgb2gray(I);
%Create a new image using imclose function on the original image
%Using lines for 20 pixels at a given angle.
%imclose function conducting Erosion and Dilation
background = imclose(I,strel('line',20,angleofScan));
%Perform Erode using disk form of 5 pixels
background = imerode(background,strel('disk',5));
%Create a new image containing the difference
%between the processed image and the original image
I2= background - I;
%Spead the difference image histogram to both edges
I3 = imadjust(I2);
%Finds the image threshold using Otsu's method
%Once found the image is converted to black and white
level = graythresh(I3);
bw = im2bw(I3,level);
%Background noise is removed
bw2 = bwareaopen(bw, SmallestObjectToRemove);
%Create an arrays of objects each containing
%an arrays of pixels of the object
%objects are a white area surrounded by black pixels
cc(counter) = bwconncomp(bw2, 8);
%Generate a structues based arrays of all
%the object in all images that were generated
%in different scan angles. The data contains
%major and minor asix leangth of each and every object
%detected during the scan
if counter==1
graindataMajorArray.graindataMajor = regionprops(cc, 'MajorAxisLength');
graindataMinorArray.graindataMinor = regionprops(cc, 'MinorAxisLength');
%Initiate final result by
%simply collecting the first image
FinalImage = bw2;
else
graindataMajorArray(counter).graindataMajor = regionprops(cc(counter), 'MajorAxisLength');
graindataMinorArray(counter).graindataMinor = regionprops(cc(counter), 'MinorAxisLength');
end
end
%Initiate final result by
%simply using the first image data
ccFinal = cc(1);
%Scan and compare Images
FinalImageColor = uint8(FinalImage);
for compareCounter=2:1:counter
%Scan each object in the image and compare it to the
%first processed image object. If a new item is found
%it is added to the "FinalImage".
%New image - Object look
for NewObjectNumber=1:1:cc(compareCounter).NumObjects
FlagObjectFound=0;
%Final image - objects loop
for FinalObjectNumber=1:1:ccFinal.NumObjects
%determine if there is a reasonable familiarity between objects
FamiliarObject = sum(FinalImage(cell2mat(cc(compareCounter).PixelIdxList(NewObjectNumber))) >=1)/length(cell2mat(cc(compareCounter).PixelIdxList(NewObjectNumber))) * 100;
if isequal(cc(compareCounter).PixelIdxList(NewObjectNumber),ccFinal.PixelIdxList(FinalObjectNumber)) || FamiliarObject>= 90
FlagObjectFound=1;
break;
end
end
if FlagObjectFound==0
%Update final image
FinalImage(cell2mat(cc(compareCounter).PixelIdxList(NewObjectNumber)))=1;
FinalImageColor(cell2mat(cc(compareCounter).PixelIdxList(NewObjectNumber)))=compareCounter*30;
%Update final image objects data
ccFinal.Connectivity=ccFinal.Connectivity+1;
ccFinal.NumObjects=ccFinal.NumObjects+1;
ccFinal.PixelIdxList(ccFinal.NumObjects)=cc(compareCounter).PixelIdxList(NewObjectNumber);
end
end
end
rgbImage = ind2rgb(FinalImageColor, colormap(jet));
figure, imshow(rgbImage);
ccFinalRescaled8 = bwconncomp(FinalImage, 8);
FinalDataMajorPixles = regionprops(ccFinalRescaled8, 'MajorAxisLength');
FinalDataMinorPixles = regionprops(ccFinalRescaled8, 'MinorAxisLength');
for Count=1:1:ccFinalRescaled8.NumObjects
FinalDataMajornm(Count) = nm_per_plx*FinalDataMajorPixles(Count).MajorAxisLength;
FinalDataMinornm(Count) = nm_per_plx*FinalDataMinorPixles(Count).MinorAxisLength;
end
%export data to excle
MajorAxisLength = 'MajorAxisLength.xlsx';
xlswrite(MajorAxisLength,FinalDataMajornm(:));
MinorAxisLength = 'MinorAxisLength.xlsx';
xlswrite(MinorAxisLength,FinalDataMinornm(:));
end
%%
% Extract the scale bar from the picture
% Calculate its length and returns the
% pixel and nm ratio: 1 pixed = PlxPerNM nm
function NMPerPlx = CalculateNMPerPLX(img_res,RescaleSize)
I = imread('Target.tif');
I = imresize(I,RescaleSize);
I = rgb2gray(I);
I= imcrop(I,[0 750 500 50]);
background = imclose(I,strel('line',50,0));
I3=background;
level = graythresh(I3);
bw = im2bw(I3,level);
bw2 = 1- bwareaopen(bw, 50);
%presents the scale bar:
figure, imshow(bw2);
cc = bwconncomp(bw2, 8);
tmp = regionprops(cc, 'BoundingBox');
graindataMajor = tmp.BoundingBox(3) + 2;
NMPerPlx=(img_res*RescaleSize)/graindataMajor;
end