Randomly deforming my curve

3 ビュー (過去 30 日間)
Xiao Zhang
Xiao Zhang 2019 年 7 月 1 日
コメント済み: Image Analyst 2021 年 2 月 17 日
I have a 1D curve like this:
that I want to randomly deform so that the height of each peaks can be slightly different, like this:
Note that here I am not adding random noise; my curve is still smooth and continued, but the peaks have different height (or better, have slightly different locations).
Is there any simple method to achieve such a transformation to my initial curve?
The reason why I want to do this, is because I would like to grow my population of input to do some Supervised Machine learning on recognizing specific patterns of my curves (e.g., when the 1st peak is split into two smaller ones, etc.).
I should have uploaded the array of blue curve in the attachment.
Thank you!
  2 件のコメント
TheoBoveri
TheoBoveri 2021 年 2 月 17 日
I would also be interested in a solution to this.
Have you, by any chance, already found a way to do this?
I'm trying to do this on a 2d Matrix for a similar application.
Just Manuel
Just Manuel 2021 年 2 月 17 日
編集済み: Just Manuel 2021 年 2 月 17 日
instead of random noise, you could try multiplying your data by some smooth curve that oscillates around 1.
Something along the lines of
deform = 1 + 0.5 .* rand(1) .* sin(1:length(your_data));
deformed = your_data .* deform;
Cheers
Manuel

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

回答 (1 件)

Image Analyst
Image Analyst 2021 年 2 月 17 日
編集済み: Image Analyst 2021 年 2 月 17 日
Try this:
% Initialization steps.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 13;
s = load('x.mat')
signal = s.x;
subplot(3, 1, 1);
plot(signal, 'b-', 'LineWidth', 2);
grid on;
xlabel('Index', 'FontSize', fontSize);
ylabel('Signal', 'FontSize', fontSize);
% Find valleys
[valleyValues, valleyIndexes] = findpeaks(-signal)
hold on;
% plot(valleyIndexes, -valleyValues, 'rv');
% Plot red lines to divide the plot into different "zones".
for k = 1 : length(valleyIndexes)
xline(valleyIndexes(k), 'Color', 'r');
end
% Define how many new signals you want to generate
numNewSignals = 3;
% Plot it.
subplot(3, 1, 3);
plot(signal, '-', 'LineWidth', 2);
hold on;
% Get plot colors for each line from the hsv colormap function.
plotColors = hsv(numNewSignals);
legendStrings{1} = 'Original Signal';
for n = 1 : numNewSignals
% Make an array of random numbers between 0 and 2 - one for each zone.
amplitudeFactors = ones(size(signal)) * rand(1);
for k = 1 : length(valleyIndexes)
amplitudeFactors(valleyIndexes(k) : end) = 2 * rand(1);
end
h2 = subplot(3, 1, 2);
hold on;
plot(amplitudeFactors, '-', 'Color', plotColors(n, :), 'LineWidth', 2);
grid on;
xlabel('Index', 'FontSize', fontSize);
ylabel('Amplitude Factor', 'FontSize', fontSize);
% Get new varied signal
newSignal = signal .* amplitudeFactors;
h3 = subplot(3, 1, 3);
plot(newSignal, '-', 'Color', plotColors(n, :), 'LineWidth', 2);
xlabel('Index', 'FontSize', fontSize);
ylabel('New Signal', 'FontSize', fontSize);
grid on;
legendStrings{n + 1} = sprintf('New Signal %d', n);
end
legend(h2, legendStrings(2:end));
legend(h3, legendStrings);
  3 件のコメント
TheoBoveri
TheoBoveri 2021 年 2 月 17 日
Wow, thanks for the quick solution. I have one additional question.
When generating the new data I would like to keep the area under the curve the same. So if I lower the maximum of a peak it gets wider etc.
In my data the peaks are clearly separated and won't bleed into each other when widening. Also my baseline is always at 0. I attached a respective file to the post.
Do you have any approach to this?
Many many thanks for your help!
Image Analyst
Image Analyst 2021 年 2 月 17 日
Youi'd have to extract out each zone to its own signal and own x-axis. Then redefine the x over the range of the zone. Like instead of going from 15 to 20, x now goes from 10 to 25 or whatever. Then use trapz() to get the areas of the original and expanded signals. Then scale it by the ratio of the areas. Then take all the x axes from all the zones and combine them together so we now have all the x's. Use interp2() to interpolate each zone at the "extra" x points the neighboring zones might have added in. Then combine all the Y signals together by adding.

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

カテゴリ

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

Community Treasure Hunt

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

Start Hunting!

Translated by