matlab determine a curve
Show older comments
Imagine i have an original plot with superimposed '8' shape curves (the curves are all different but similar to the '8' shape). Does anyone know how to obtain a mean curve having a matrix with the correspondent x,y points from the original plot? I mean, I pretend a medium single curve.
Any code or just ideas would be very very helpful for me. Thank you very very much!
7 Comments
Image Analyst
on 16 Sep 2012
You'd need to upload a picture. Also, do any of the curves overlap along any part of themselves? If so, how can we take that into account unless you have all the individual curves? For example 10 curves perfectly overlapped plus one slightly shifted will appear as just two curves, but obviously you don't want to average just two sets of coordinates.
Image Analyst
on 16 Sep 2012
Do you have the individual curves? You should, if you plotted it.
joo
on 16 Sep 2012
Image Analyst
on 16 Sep 2012
Edited: Image Analyst
on 16 Sep 2012
Interesting question. I can't think of anyway off the top of my head that's simple. All I can think of are imaging-based approaches like assigning them to pixels, adding together, blurring the image, and trying to find medial axis. Or maybe you can align them all by searching for the left-most point and using circshift to wrap around all the rows of your arrays so that the left-most point is always the top row. That might work for certain situations, like the shapes in your demo.
Maybe you should ask in the newsgroup. Roger Stafford monitors that, and he is an excellent mathematician and he'd probably know of a method right away.
Go ahead and upload your workbook to your favorite filesharing website - one that does not require me to register for anything to download it.
Image Analyst
on 18 Sep 2012
Can you post your code where you use xlsread to read it in and loop over each curve to find the left-most part and record its row? And your code to use circshift to align them? Can you do any of that to help us help you?
Accepted Answer
More Answers (1)
8 Comments
Image Analyst
on 20 Sep 2012
Sure, you can use that point. It doesn't really matter. Of course the distances will be different but that doesn't matter when all you need to do is to determine what element the loop turns around at. You can pick any point that's sort of off the end of the loop end. If you want, simply fit all the points to a line with polyfit() and then use polyval() to find a point exactly along the mean axis of all the curves. You can do that but you'd probably get pretty much the same elements that define where the curve turns around at. All right, here -- I did the whole thing for you.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
imtool close all; % Close all imtool figures.
clear; % Erase all existing variables.
workspace; % Make sure the workspace panel is showing.
format longg;
format compact;
fontSize = 20;
folder = 'C:\Users\Mark\Documents\Temporary';
baseFileName = 'livro1.xlsx';
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% File doesn't exist -- didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
[num txt raw] = xlsread(fullFileName);
x = num(:, 1);
y = num(:, 2);
% Plot x
subplot(2,2,1);
plot(x, 'b-');
xlabel('Element Number', 'FontSize', fontSize);
ylabel('X', 'FontSize', fontSize);
title('X', 'FontSize', fontSize);
grid on;
% Plot y
subplot(2,2,2);
plot(y, 'b-');
xlabel('Element Number', 'FontSize', fontSize);
ylabel('Y', 'FontSize', fontSize);
title('Y', 'FontSize', fontSize);
grid on;
% Plot curves
subplot(2,2,3);
plot(num(:, 1), num(:, 2), 'b-');
title('X', 'FontSize', fontSize);
xlabel('X', 'FontSize', fontSize);
ylabel('Y', 'FontSize', fontSize);
grid on;
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
% Calculate distance from (50,360) of every point.
distances = sqrt((x - 450).^2 + (y - 550).^2)
subplot(2,2,4);
plot(distances, 'b-');
title('Distance from (450, 550)', 'FontSize', fontSize);
xlabel('index', 'FontSize', fontSize);
ylabel('Distances', 'FontSize', fontSize);
grid on;
% Find valleys in distances to find out where it turned around.
[peakValues, indexesAtPeaks] = findpeaks(distances)
% Take just the "good" peaks = those that are higher than
goodPeaks = peakValues > 300;
peakValues = peakValues(goodPeaks);
indexesAtPeaks = indexesAtPeaks(goodPeaks);
% Plot them.
hold on;
plot(indexesAtPeaks, peakValues, 'r*');
% We only want to go between the peaks because the
% data before the first peak and after the last peak
% are only partial peaks.
% Average the x and y between the peaks
figure;
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
sumX = zeros(1,100);
sumY = zeros(1,100);
count = 0;
for peak = 1 : length(indexesAtPeaks)-1
index1 = indexesAtPeaks(peak);
index2 = indexesAtPeaks(peak+1)-1;
% Extract the curve between those indexes.
thisX = x(index1:index2);
thisY = y(index1:index2);
% Skip bad (short) ones;
if length(thisX) < 5
break;
end
% Plot them.
hold on;
plot(thisX, thisY, 'r*');
grid on;
% These may not all be the same number of elements for every peak.
% So we need to interpolate before we can average.
originalIndexes = 1 : length(thisX);
interpolatedIndexes = linspace(originalIndexes(1), originalIndexes(end), 100); % Interpolate 100 points in our curves.
interpX = interp1(originalIndexes, thisX, interpolatedIndexes, 'spline');
interpY = interp1(originalIndexes, thisY, interpolatedIndexes, 'spline');
% Plot the interpolated curve.
plot(interpX, interpY, 'b-');
% Sum them up
sumX = sumX + interpX;
sumY = sumY + interpY;
count = count + 1; % # times through the loop.
end
meanX = sumX / count;
meanY = sumY / count;
% Plot the mean curve.
plot(meanX, meanY, 'g-', 'LineWidth', 3);
joo
on 28 Sep 2012
Image Analyst
on 29 Sep 2012
If you look at the curves I plotted, you'll see there is a little tiny peak at the bottom of the curve. This small peak is at the wrong end plus it's so small that it's basically noise. So I put in that code to ignore those small spurious peaks.
Image Analyst
on 29 Sep 2012
Sorry - you're right. It should have been continue instead of break so that it would get the rest of the peaks instead of quitting after peak 5.
joo
on 30 Sep 2012
joo
on 5 Oct 2012
Image Analyst
on 5 Oct 2012
I'm calculating the Euclidean distance from some point way off the end of the curve's travel to the points on the curve using the Pythagorean Theorem, which is the sqrt of the sum of the squares. That distance oscillates as the point on the curve gets closer and farther away from the fixed, distant point as the curve point travels.
Categories
Find more on Get Started with MuPAD in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!