Template matching between 1d frequency curves using normxcorr2
9 views (last 30 days)
Show older comments
Hi,
I'm trying to use 2d cross correlation between 1d dimensional frequency curves (frequencies between 6000 and 22000 Hz) to find if a template curve is present in a test one which is bigger:
Template curve:
Test curve:
I'm willing to use two dimensional cross correlation between both curves using normxcorr2 but I'm not quite sure the most efficient way to do this.
I've tried to convert both curves to binary image arrays, and then applying nomxcorr2 using:
img_template=bsxfun(@eq, 1:22000,curve_template);
img_test=bsxfun(@eq, 1:22000,curve_test);
c=normxcorr2(img_template,img_test);
but this way the 2d arrays are huge (77x22000 and 5703x22000) and the results are difficult to plot ( because of memory issues) and so to analize:
figure;mesh(img_template');hold on;
view([0 90]);
mesh(img_test);
figure;
surf(c)
Any clue on how to do this template matching between curves in a more efficcient way?
2 Comments
Matt
on 1 Jul 2024
Hi,
If you want to detect, in a 1D signal, a certain pattern you can simply use 1D correlation. No need, except if I missed your goal, to convert the data like you are.
% normxcorr2 works on 1d data:
plot(normxcorr2(curve_template,curve_test))
% but it also work on N signals of length M
n = 512;
m=1024;
imagesc(normxcorr2(curve_template,rand(m,n)))
and if you want to go faster on many signals, you can drop the normalisation part and simply do a convolution between your signals, and the pattern.
imagesc(conv2(curve_template,rand(m,n),'valid'))
Answers (1)
Milan Bansal
on 25 Jul 2024
Hi David Santos,
To perform template matching between 1D frequency curves in a more efficient way, you can use 1D cross-correlation instead of converting your curves to 2D arrays. This approach will be much more memory-efficient and easier to handle.
Here's how you can do it:
- Normalize the curves: Make sure both curve_template and curve_test are normalized. This can be done by subtracting the mean and dividing by the standard deviation.
- Use xcorr: Instead of normxcorr2, you can use xcorr to perform cross-correlation on 1D arrays. Here is the documentation of xcorr:https://www.mathworks.com/help/matlab/ref/xcorr.html
- Find the peak: The peak in the cross-correlation result will indicate the best match between the template and the test curve.
Here's an example code to perform these steps:
load curves
% Normalize the curves
curve_template = (curve_template - mean(curve_template)) / std(curve_template);
curve_test = (curve_test - mean(curve_test)) / std(curve_test);
% Perform 1D cross-correlation
[corr_result, lags] = xcorr(curve_test, curve_template);
% Find the peak of the correlation result
[~, peak_index] = max(corr_result);
% The lag corresponding to the peak indicates the best match position
best_match_lag = lags(peak_index);
% Plot the cross-correlation result
figure;
plot(lags, corr_result);
xlabel('Lag');
title('Cross-Correlation between Test Curve and Template Curve');
% Plot the best match
figure;
plot(curve_test(best_match_lag:best_match_lag+length(curve_template)-1));
hold on;
plot(curve_template, 'r');
legend('Test Curve Segment', 'Template Curve');
title('Best Match between Test Curve and Template Curve');
Hope it helps!
See Also
Categories
Find more on Spectral Estimation 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!