How to find the count of vertical lines in an image using Fourier Transform in MATLAB?

25 views (last 30 days)
I have taken an image of a grid and have obtained the vertical lines from the grid image using the following code.
But I now want to calculate the number of lines present using Fourier Transform on the "ver.jpeg" file.
clc
clear
close all
warning off
x=im2gray(imread('img-grid.png'));
x=~imbinarize(x);
%line structuring element
%2nd param- line length = 20px
%3rd param- angle = 90 for vertical lines
SE = strel('line',20,90);
%applying erosion to remove horizontal lines
s=imerode(x,SE);
%erosion shrinks vertical lines as well so applying dilation
s=imdilate(s,SE);
imwrite(s, 'ver.jpeg');
imshow(x)
title("Original")
imshow(s)
title("Vertical lines")
The below code I have used fft() function to get corresponding values for the 1st pixel row of image "ver.jpeg" but I am unable to make sense of the output.
%fourier transform
x=im2gray(imread('ver.jpeg'));
f=imbinarize(x);
row1 = f(1, :);
imshow(row1)
Y = abs(fft(row1));
plot(Y)
hold on;
plot(row1)
hold off;
subplot(2, 1, 1);
plot(Y)
title("fft(row1)")
subplot(2, 1, 2);
plot(row1)
title("row1 of ver.jpeg")
Can someone please help me how to get the count of lines from the image?
Thank you in advance.

Answers (3)

Jonas
Jonas on 28 Nov 2022
% create sample image
imgLine=repmat([ones(1,5) zeros(1,20)],[1 10]);
% shift it a bit to force broken (incomplete) lines
imgLine=circshift(imgLine,8);
imgLine = 1×250
0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
tiledlayout(3,1);
nexttile();
imshow(imgLine)
fMax=numel(imgLine)/2;
freq=-numel(imgLine)/2:numel(imgLine)/2-1;
nexttile()
plot(freq,abs(fftshift(fft(imgLine))))
nexttile()
% without mean (DC) value
plot(freq,abs(fftshift(fft(imgLine-mean(imgLine)))))
xlabel('oscillations per image')
xlim([-15 15])
% first Peak seems to be near 10 -> 10 complete lines per image
as you can see, the question is how you want to count not cemplete lines. In itself, there were 9 complete lines and 2 divided, but 2 divided give 1 complete
  2 Comments
Jonas
Jonas on 28 Nov 2022
yes, thats possible, e.g. like that
imgLine=repmat([ones(1,5) zeros(1,20)],[1 10]);
% shift it a bit to force broken (incomplete) lines
imgLine=circshift(imgLine,8);
tiledlayout(4,1);
nexttile();
imshow(imgLine)
fMax=numel(imgLine)/2;
freq=-numel(imgLine)/2:numel(imgLine)/2-1;
nexttile()
plot(freq,abs(fftshift(fft(imgLine))))
nexttile()
% without mean (DC) value
withoutMean=abs(fftshift(fft(imgLine-mean(imgLine))));
plot(freq,withoutMean)
xlabel('oscillations per image')
xlim([-15 15])
withoutMean(freq<0)=[];
freq(freq<0)=[];
nexttile
findpeaks(withoutMean,freq,'NPeaks',1,'MinPeakHeight',0.8*max(withoutMean))
% you could use the output of findpeaks to get location or, if the value is
% the biggest
[~,idx]=max(withoutMean);
freq(idx)
ans = 10

Sign in to comment.


Bjorn Gustavsson
Bjorn Gustavsson on 28 Nov 2022
Why in the world do you want to use the Fourier transform to do that? You might be OK-ish for this specific pattern since it (superficially) seems regular, for that you could just check the first non-zero-frequency peak in the fft-spectrum. You know that the first component corresponds to an intensity-variation with a period-length of the full sequence, the second 2 component corrsponds to intensity-variations with 2 full periods over the entire sequence and on and on.
BUT: Why in the world do you want to use the Fourier transform to do this? In every non-classroom situation you can count on the signal being quasi-periodic - and in that case this is going the extra step to create a far more tricky problem.
  3 Comments
Bjorn Gustavsson
Bjorn Gustavsson on 29 Nov 2022
Yup. What do you count as a vertical line in this weave (is it? Hopefully correct identification of cloth?)? To my eyes there seem to be at least 2 different coloured threads in the vertical direction, one yellow-orange and one dark green or brownish, do they count as 2 different vertical lines? One other idea is to count how many horizontal white dashes there is along one row, that would correspond to roughly half the number of vertical threads (possibly a quarter?).

Sign in to comment.


Image Analyst
Image Analyst on 29 Nov 2022
I'd make a mask of the white. Then erase that part of the image. Then I'd sum the image vertically. You should get a signal with a bunch of peaks. Use findpeaks to locate their coordinates. Seems pretty easy but let us know if you have problems. Doing it in the spatial domain like this will let you locate every stripe even if they are not evenly spaces.
If you want to use Fourier you can take the 1-D fft of the sum signal and look for the dominant (non-DC) peak. Or take the 2D fft and look for the dominant peak along the y axis (since vertical stripes will diffract horizontally).
You could do a similar process on the white mask if you want the frequency of the white threads.
Doing it in the Fourier domain will give you the average frequency of the stripes, but not each one individually.

Products


Release

R2022b

Community Treasure Hunt

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

Start Hunting!