How can I process the image and extract the spacing between individuals dots in a row ?

6 ビュー (過去 30 日間)

採用された回答

Image Analyst
Image Analyst 2023 年 4 月 23 日
Like @Walter Roberson said,
  1. Use the radon transform to discover the angle at which your spot array is rotated. See attached demo.
  2. Then use imrotate to align your spot arrays with the edges of the image.
  3. Then threshold and use regionprops to get the spot centroids.
  4. 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.
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 件のコメント
DGM
DGM 2023 年 4 月 23 日
編集済み: DGM 2023 年 4 月 23 日
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]
ans = 1×2
34.2487 38.2184
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.

サインインしてコメントする。

その他の回答 (3 件)

Walter Roberson
Walter Roberson 2023 年 4 月 22 日
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 件のコメント
Walter Roberson
Walter Roberson 2023 年 4 月 23 日
編集済み: Walter Roberson 2023 年 4 月 23 日
or imbinarize with ForegroundPolarity "dark"
DGM
DGM 2023 年 4 月 23 日
編集済み: DGM 2023 年 4 月 23 日
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
chicken vector 2023 年 4 月 22 日
編集済み: chicken vector 2023 年 4 月 22 日
img = imread('image.png');
[centers, radii, metric] = imfindcircles(img,[5 18]);
You can compute the distances from centers.
Also, see this question on how to rotate an image with circles.

DGM
DGM 2023 年 4 月 22 日
編集済み: DGM 2023 年 4 月 22 日
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
c = 2×1
38.2507 34.5072
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.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by