Tracing Line from an Image

24 ビュー (過去 30 日間)
yjin
yjin 2023 年 2 月 10 日
編集済み: Matthieu 2023 年 2 月 10 日
I have a 2D matrix that looks like the attached image when plotted using the imagesc function. I wonder if there is a simple method to trace a single line (1D data) that would follow the yellow curves going from the left to right. Thanks a lot for your help!
  2 件のコメント
Walter Roberson
Walter Roberson 2023 年 2 月 10 日
Do you need multiple lines such as bright middle and the two orange bands around it? Or just the bright middle? Or do you need to trace lines of constant value (in which case, contour())?
yjin
yjin 2023 年 2 月 10 日
I just need the bright middle. And simply finding the index of the brightest value of each column doesn't work well because of the noise in the image, especially around the region where x = 4000.
Ideally, I would like to trace a smooth line around the bright middle, perhaps by applying a low pass filter after initial tracing.

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

採用された回答

DGM
DGM 2023 年 2 月 10 日
I imagine there are better ways, but here's my hamfisted attempt:
% all i have is a screenshot, so convert that to grayscale
inpict = imread('image.png');
CT = parula(256);
% this is a uint8 grayscale image
inpict = rgb2ind(inpict,CT);
% create a working copy
wpict = inpict;
wpict(1:34,:) = 0; % trim the junk off the top
wpict = fliplr(wpict); % process from RTL
% try to follow the path, starting from R to L
w = 25; % window half-width
sz = size(inpict);
ydata = zeros(1,sz(2));
for c = 1:sz(2)
thiscol = wpict(:,c);
if c == 1
[~,ydata(c)] = max(thiscol);
else
yp = ydata(c-1);
thiscol(1:max(yp-w,1)) = 0;
thiscol(min(yp+w,sz(1)):end) = 0;
[~,ydata(c)] = max(thiscol);
end
end
ydata = fliplr(ydata); % reorient to undo input flip
% plot the result
imshow(inpict); hold on
hp = plot(ydata,'b');
hp.LineWidth = 2;
This is a fragile example and will easily break on other images or if this particular image is processed in the opposite direction. Like I said, I imagine there are better ways.

その他の回答 (1 件)

Matthieu
Matthieu 2023 年 2 月 10 日
編集済み: Matthieu 2023 年 2 月 10 日
n= 30 ; m= 40 ;
A = rand(n,m) ;
B = A ; B(B ~= max(B)) = 0 ;
index = find(B) ;
[q,r] = quorem(sym(index),sym(n)) ;
r(r == 0) = n ;
imagesc(A)
hold on
plot(1:m,r,"linewidth",3,"color","r")
as max(A) yields the maximum value of the array line-wise.
This example show in the case of random matrix A, but you have noisy data around a clearly identifiable value. Apply low-pass filter on data if it is noisy, or try approximating better than taking max value, as my method relies on too few information.
Just bear in mind it might not be the most efficient method at all.
EDIT : of course it doesn't work with multiple same values in columns. Using @DGM 's reply, here's an updated version (using your picture and not a random matrix) :
pict = imread("image.png") ;
graypict = rgb2ind(pict,parula(256)) ;
A = double(graypict) ;
A(1:35,:) = [] ; % trimming picture from bad data on top
B = A ; % making copy of array
[n,m] = size(A) ;
B(B ~= max(B)) = 0 ; % setting to zero all non-maximum values of picture
index = zeros(1,m) ;
for i = 1:m % finding indexes of all first and last non-zero values in picture
index_lasts(i) = find(B(:,i),1,'last') ;
index_frsts(i) = find(B(:,i),1,'first') ;
end
[ql,rl] = quorem(sym(index_lasts),sym(n)) ; % getting the n-related part of the index. q is the m-related.
[qf,rf] = quorem(sym(index_frsts),sym(n)) ;
rf(rf == 0) = n ; % setting as n all "0" indexes (non-valid for array idnexing)
rl(rl == 0) = n ;
%if you want mean of data acquired :
r_average = rf+rl/2 ;
%plotting results.
f = figure ;
f.Position = [50 50 1700 350];
imagesc(A)
hold on
plot(1:m,rf,"linewidth",2,"color","r")
plot(1:m,rl,"linewidth",2,"color","k")
Your data is quite noisy : consider applying on picture a finely selected convolution matrix to reduce local extremas from noise.

カテゴリ

Help Center および File ExchangeImages についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by