- Use the radon transform to discover the angle at which your spot array is rotated. See attached demo.
- Then use imrotate to align your spot arrays with the edges of the image.
- Then threshold and use regionprops to get the spot centroids.
- If you know how many rows and columns there will be you can use kmeans to get the mean row and column of all the spot rows. If you don't know how many there will be, or if a row or column might be complete absent of any spots, then you can ask kmeans to figure out the best k to use.
How can I process the image and extract the spacing between individuals dots in a row ?
5 views (last 30 days)
Show older comments
0 Comments
Accepted Answer
Image Analyst
on 23 Apr 2023
If you have a rough template of where the spot locations could be, that might be the easiest. Just scan the centroids from regionprops and decide which template spot each spot falls closest to.
1 Comment
DGM
on 23 Apr 2023
Edited: DGM
on 23 Apr 2023
I've never used radon(), and I almost never use kmeans(), so I figured I'd go ahead and try.
% image is indexed (don't actually need the map though)
[inpict,~] = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1363878/image.png');
% convert to a logical image; cleanup
mask = inpict == 2; % foreground is black
mask = bwareaopen(mask,150); % get rid of speckles
imshow(mask,'border','tight')
% do radon transform
theta = 0:180;
[R,~] = radon(mask,theta);
% find angle to rotate image back
[~,idx] = max(R(:));
[~,c] = ind2sub(size(R),idx);
correctionangle = 90-mod(theta(c),90);
% rotate image
mask = imrotate(mask,correctionangle);
imshow(mask,'border','tight')
% get centroids
S = regionprops(mask,'centroid');
C = vertcat(S.Centroid);
% cluster rows,cols independently
% i'm presuming a particular number of rows,columns are present
[~,meanrows] = kmeans(C(:,2),9);
[~,meancols] = kmeans(C(:,1),10);
% get average spacing
rowpitch = mean(diff(sort(meanrows)));
colpitch = mean(diff(sort(meancols)));
% the answer
[rowpitch colpitch]
Bear in mind that this only corrects a simple rotation transformation. If the pads are not grid-aligned because they've been subject to projective transformation, all bets are off.
More Answers (3)
Walter Roberson
on 22 Apr 2023
Invert the image so that the black-on-white becomes white-on-black. regionprops looking for the centroids and extrema. The angle between the upper left extrema and the upper right extrema gives you a rotation angle. Apply a transform matrix to the coordinates: translate to move the upper left extrema to the center, rotate the centroid coordinates by the angle... no need to translate back for this purpose. This should align centroids horizontally; you should be able to ismembertol() on the y coordinates to find all centroids on the same x row, and then you can find the difference between the corresponding (rotated) x coordinates.
3 Comments
Walter Roberson
on 23 Apr 2023
Edited: Walter Roberson
on 23 Apr 2023
or imbinarize with ForegroundPolarity "dark"
DGM
on 23 Apr 2023
Edited: DGM
on 23 Apr 2023
Bear in mind that the image you gave is an indexed image. If you want to use either, you'd need to convert it to a grayscale image.
In the answer I gave, I showed a simple method to convert the given indexed image to a clean logical image.
% image is indexed (don't actually need the map though)
[inpict,~] = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1363878/image.png');
% convert to a logical image; cleanup
mask = inpict == 2; % foreground is black
mask = bwareaopen(mask,150); % get rid of speckles
imshow(mask,'border','tight')
chicken vector
on 22 Apr 2023
Edited: chicken vector
on 22 Apr 2023
img = imread('image.png');
[centers, radii, metric] = imfindcircles(img,[5 18]);
You can compute the distances from centers.
0 Comments
DGM
on 22 Apr 2023
Edited: DGM
on 22 Apr 2023
Do you need row spacing, or do you simply need the spacing between each blob and its neighbors?
You can also use pdist2() if you have the stats toolbox.
If you do want the row spacing, Walter's suggestion is probably a good place to start. I'm just going to throw this out there.
% image is indexed
[inpict map] = imread('pads.png');
% convert to a logical image; cleanup
mask = inpict == 2;
mask = bwareaopen(mask,150);
% get centroids
S = regionprops(mask,'centroid');
C = vertcat(S.Centroid);
% get distances to 4-neighbors
D = pdist2(C,C);
ref = min(nonzeros(D))*sqrt(2);
D(D>=ref) = 0;
% show distribution of 4-neighbor distances
histogram(nonzeros(D))
% try clustering
[idx c] = kmeans(nonzeros(D),2);
c
If there is a distinct difference between row spacings, that may tell you what they are. It won't directly tell you which is which or whether those spacings even correspond to orthogonal directions, but perhaps this partial example will help verify the results you get from a more useful solution. In this case, those values do correspond to the column and row spacings.
0 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!