finding edge/ plot from image/ maze

2 次查看(过去 30 天)
Soroush Sabbaghy
Soroush Sabbaghy 2023-3-28
编辑: DGM 2023-3-28
I want to extract plot form this image. what approch works the best?

回答(3 个)

KSSV
KSSV 2023-3-28
You can use contour.

Image Analyst
Image Analyst 2023-3-28
I'd try using
indexedImage = rgb2ind(rgbImage, 8);
to get an indexed image. Then find out the index for each color and ignore the ones for black and white.
Then scan your image column-by-column finding the first row where each index occurs. For any missing columns (like where one color went underneath a different color, use interp1 to interpolate the value. Something like
[rows, columns, numberOfColorChannels] = size(rgbImage);
brownCurve = nan(1, columns);
redCurve = nan(1, columns);
purpleCurve = nan(1, columns);
greenCurve = nan(1, columns);
orangeCurve = nan(1, columns);
blueCurve = nan(1, columns);
for col = 1 : columns
thisColumn = indexedImage(:, col);
% Find if there is a red curve in this column.
row = find(thisColumn == redIndex, 1, 'first');
if ~isempty(row)
redCurve(col) = row;
end
% Find if there is a brown curve in this column.
row = find(thisColumn == brownIndex, 1, 'first');
if ~isempty(row)
brownCurve(col) = row;
end
end
% Interpolate missing data points
missingIndexes = isnan(redCurve);
x = 1 : columns;
redCurve = interp1(x(~missingIndexes), y(~missingIndexes), x);
% Etc.
Of course there is a lot missing there but I'm confident you'll be able to finish it, right?

DGM
DGM 2023-3-28
编辑:DGM 2023-3-28
I'm assuming that the goal is to take the second image and reduce it to plottable data such as would generate a plot like the first one. I'm just going to do this the same way I always do it, so see the links for explanations, examples, and more links to the same. The same commentary applies here, with the additional caveat that I have no idea what this plot actually means.
See the attached SVG file.
% using the following FEX tools:
% https://www.mathworks.com/matlabcentral/fileexchange/72225-load-svg-into-your-matlab-code
% filename of manually-fit svg file
fname = 'drawing.svg';
% data range from original image axis labels
% this is where the rectangle is drawn in the SVG
xrange = [0 1]; % this is arbitrary
yrange = [0 60];
% spline discretization parameter [0 1]
coarseness = 0.01;
% get plot box geometry
str = fileread(fname);
str = regexp(str,'((?<=<rect)(.*?)(?=\/>))','match');
pbx = regexp(str,'((?<=x=")(.*?)(?="))','match');
pby = regexp(str,'((?<=y=")(.*?)(?="))','match');
pbw = regexp(str,'((?<=width=")(.*?)(?="))','match');
pbh = regexp(str,'((?<=height=")(.*?)(?="))','match');
pbrect = [str2double(pbx{1}{1}) str2double(pby{1}{1}) ...
str2double(pbw{1}{1}) str2double(pbh{1}{1})];
% get coordinates representing the curve
S = loadsvg(fname,coarseness,false);
% if there are multiple paths you want to extract
% you'll need to do do the rescaling, etc for each element of S
for k = 1:numel(S) % there are multiple curves
x = S{k}(:,1);
y = S{k}(:,2);
% rescale to fit data range
x = xrange(1) + diff(xrange)*(x-pbrect(1))/pbrect(3);
y = yrange(1) + diff(yrange)*(pbrect(4) - (y-pbrect(2)))/pbrect(4);
% get rid of nonunique points
[x,idx,~] = unique(x,'stable');
y = y(idx);
% shove the prepared data back into S for later
S{k} = [x y];
end
% the last two curves are actually just marker lines used to locate M,K
% in order for these to be the "last two", they must have the highest
% z-order of the curves. Use "bring to front", "raise selection", or
% simply draw them last.
xM = mean(S{k-1}(:,1));
xK = mean(S{k}(:,1));
S = S(1:end-2); % get rid of markers
% plot the curves
for k = 1:numel(S)
x = S{k}(:,1);
y = S{k}(:,2);
plot(x,y); hold on
end
% plot the marker lines
xline(xM);
xline(xK);
grid on;
xlim(xrange)
ylim(yrange)
% set xticks and labels
xticks([0 xM xK 1])
xticklabels({'\Gamma' 'M' 'K','\Gamma'})
It's difficult to tell which curves are which when they intersect, but I am assuming that the final curve ordering is simply based on height. If the curve trajectories need to be done differently, then simply edit the attached SVG.
%% split and order curves based on height
% interpolate each curve on to a common abcissa
npoints = 1000;
xnew = linspace(xrange(1),xrange(2),npoints);
ynew = zeros(numel(S),npoints);
for k = 1:numel(S)
x = S{k}(:,1);
y = S{k}(:,2);
ynew(k,:) = max(interp1(x,y,xnew),yrange(1));
end
ynew = sort(ynew,1,'descend');
% plot the curves
clf
plot(xnew,ynew)
% plot the marker lines
xline(xM);
xline(xK);
grid on;
xlim(xrange)
ylim(yrange)
% set xticks and labels
xticks([0 xM xK 1])
xticklabels({'\Gamma' 'M' 'K','\Gamma'})
If instead, the goal is to extract the curves from both images, then simply perform the same transcription on the first image using a vector graphics editor.

Community Treasure Hunt

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

Start Hunting!

Translated by