How do I detect the x,y co-ordinates of the location of the onion after it has been detected by the cross correlation program?
You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Show older comments
I am using a cross correlation program to detect the location of a particle in many frames and I used the demo code below to develop my program, how do I get the x, y coordinates of the particle in each frame after it has been detected by the cross correlation program
% Demo to use normxcorr2 to find a template (a white onion)
% in a larger image (pile of vegetables)
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;
% Check that user has the Image Processing Toolbox installed.
hasIPT = license('test', 'image_toolbox');
if ~hasIPT
% User does not have the toolbox installed.
message = sprintf('Sorry, but you do not seem to have the Image Processing Toolbox.\nDo you want to try to continue anyway?');
reply = questdlg(message, 'Toolbox missing', 'Yes', 'No', 'Yes');
if strcmpi(reply, 'No')
% User said No, so exit.
return;
end
end
% Read in a standard MATLAB color demo image.
folder = fullfile(matlabroot, '\toolbox\images\imdemos');
baseFileName = 'peppers.png';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
if ~exist(fullFileName, 'file')
% 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.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
rgbImage = imread(fullFileName);
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows columns numberOfColorBands] = size(rgbImage);
% Display the original color image.
subplot(2, 2, 1);
imshow(rgbImage, []);
axis on;
title('Original Color Image', 'FontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
smallSubImage = imcrop(rgbImage, [192 82 60 52]);
subplot(2, 2, 2);
imshow(smallSubImage, []);
axis on;
title('Template Image to Search For', 'FontSize', fontSize);
% Search the red channel for a match.
correlationOutput = normxcorr2(smallSubImage(:,:,1), rgbImage(:,:,1));
subplot(2, 2, 3);
imshow(correlationOutput, []);
title('Normalized Cross Correlation Output', 'FontSize', fontSize);
[maxCorrValue, maxIndex] = max(abs(correlationOutput(:)));
[ypeak, xpeak] = ind2sub(size(correlationOutput),maxIndex(1));
corr_offset = [(xpeak-size(smallSubImage,2)) (ypeak-size(smallSubImage,1))];
subplot(2, 2, 4);
imshow(rgbImage);
hold on;
rectangle('position',[corr_offset(1) corr_offset(2) 50 50],...
'edgecolor','g','linewidth',2);
title('Template Image Found in Original Image', 'FontSize', fontSize);
Accepted Answer
Image Analyst
on 3 Apr 2013
Looks like my code you got from this question. I noticed a small error when it's drawing the rectangle. It should read
rectangle('position',[corr_offset(1) corr_offset(2) 60 52],...
'edgecolor','g','linewidth',2);
so that the rectangle has the same width and height as the template.
Anyway, look at the 'position' property I sent into the rectangle() function. That defines the [xLeft, yTop, xWidth, yHeight] of where the template subimage occurs in the original image, as you can see because it places the rectangle in the proper location over the original image.
18 Comments
Thank you very much for responding. I slightly modified your code and instead of using the imcrop(rgbImage, [192 82 60 52]) to specify the region of interest where I want the program to run the cross correlation, I used imcrop(rgbImage, []) so that the user can specify the region of interest every time they run the program. My question now is how do I get the 'position' property to draw the rectangle that has the same dimension as the selected region, after cross correlation program has executed. Thank you.
Image Analyst
on 3 Apr 2013
Edited: Image Analyst
on 3 Apr 2013
You just need to know the size of the template image, and you have the xpeak and ypeak so you can figure out all the edges like I did.
corr_offset = [(xpeak-size(smallSubImage,2)) (ypeak-size(smallSubImage,1))];
ok thank you
when you say size of template image do you mean size of the cropped region or the size of the entire image
The template is the small image that you're basically scanning across the larger image. So it's the small, cropped, single onion picture.
I have multiple frames to cross correlate, frame_1 should be correlated with frame_2, and frame_2 should be correlated with frame_3 and so on. How do I make a loop for this cross correlation process because I have 500 frames?
Image Analyst
on 5 Apr 2013
Edited: Image Analyst
on 5 Apr 2013
Have two loops, one over i1 = 1 : numberOfFrames, and the other one (inside the first one) over i2 = i1+1 : numberOfFrames. It's just standard programming looping like you learned in your first programming class:
numberOfFrames = 6; % or 500 or whatever.
for i1 = 1 : numberOfFrames
for i2 = (i1+1) : numberOfFrames
fprintf('Now correlating frame #%d with frame #%d\n',i1,i2);
% Now do the correlation and do whatever you want with the result.
% More code goes here...
end
end
Thank you a lot
If we're done, mark as accepted.
EngStudent
on 6 Apr 2013
Edited: EngStudent
on 6 Apr 2013
Using the code you provided, I was able to use a for loop to cross correlate multiple images. Now I want to modify the program in such a way that the user would be able to select the particle from the first image (from a tiffstack)and this would serve as the template and then the user should also be able to select the region where this particle is likely to be found in the subsequent frames (this would be the larger image). After these selections, I want the cross correlation program to correlate the template with the selected region where the particle is likely to be found in the other frames. Below is the code I am working on, I am was able to select the object from the first image and also the region of interest for the subsequent frames however, as the program ran, the object in the template moves a step forward from the template so that the final iteration of the for loop has an empty template.
fontSize = 10;
file_name = 'stack013.tif'; %TIFF Stack
image_info = imfinfo(file_name);
numImg = length(image_info); %Number of images in stack
for i1=1:numImg %Read Each Frame
fprintf('Now correlating frame #%d with frame #%d\n',i1,i1+1);
rgbImage = imread(file_name,'Index', i1);
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows, columns, numberOfColorBands] = size(rgbImage);
% imshow(rgbImage, []); % Display the original color image.
% title('Original Color Image', 'FontSize', fontSize);
rect_rgbImage = [265.5 141.5 70 72];
sub_rgbImage = imcrop(rgbImage,rect_rgbImage);%Crop object of interest
figure,imshow(sub_rgbImage) % Show cropped object of interest
rect_A= [248.5 33.5 104 182];
A=imread(file_name,'Index', i1+1);%read the following image from image loop (in tiff stack)
sub_A = imcrop(A,rect_A); % Crop region of Interest
figure, imshow(sub_A) % Show cropped region of interest
axis on;
title('Template Image to Search For', 'FontSize', fontSize);
% Search the red channel for a match.
correlationOutput = normxcorr2(sub_rgbImage(:,:,1), sub_A(:,:,1));
figure, surf( correlationOutput),shading flat
figure('Position', [300 300 300 300])
imshow(correlationOutput, []);
sprintf('Normalized Cross Correlation Output of frame #%d and #%d\n',i1,i1+1);
title('Cross Correlation')
%Offset between the images found by correlation
[maxCorrValue, maxIndex] = max(abs(correlationOutput(:)))
[ypeak, xpeak] = ind2sub(size(correlationOutput),maxIndex(1))
corr_offset = [(xpeak-size(sub_rgbImage,2))
(ypeak-size(sub_rgbImage,1))]
%relative offset between position of subimages
rect_offset = [(rect_A(1)- rect_rgbImage(1))
(rect_A(2)- rect_rgbImage(2))]
%total offset
offset = corr_offset + rect_offset
xoffset= offset(1)
yoffset= offset(2)
%find where the bead is in the following frame
end
How do I make the object the template to be fixed so that it can be cross correlated with the other frames? How do I attract the image stack I'm working with?
Note: I have already given the dimensions of the template and the region of interest, but later on, I would this to be an interactive script.
You don't read in image i and image i+1 both in the loop. You read in i and compare it with the template image from the previous loop, Like this pseudocode)
template = imread(image1)
% Starting out frame 1 is the template.
for frame = 2 : numberOfFrames
thisImage = imread(thisFramesFileName)
normxcorr2(thisFrame, template);
% code to locate and crop particle...
% Now the cropped particle image from this frame
% becomes the template for next iteration.
template = thisCroppedFrame;
end
EngStudent
on 7 Apr 2013
Edited: EngStudent
on 7 Apr 2013
ok thank you. Could you please explain what these results mean, I saw them in a different code. Thank you
maxCorrValue, maxIndex] = max(abs(correlationOutput(:)))
[ypeak, xpeak] = ind2sub(size(correlationOutput),maxIndex(1))
corr_offset = [(xpeak-size(sub_rgbImage,2))
(ypeak-size(sub_rgbImage,1))]
%relative offset between position of subimages
rect_offset = [(rect_A(1)- rect_rgbImage(1))
(rect_A(2)- rect_rgbImage(2))]
%total offset
offset = corr_offset + rect_offset
xoffset= offset(1)
yoffset= offset(2)
xpeak and ypeak are the coorindates in the correlation image, which is bigger than the original images. See my code, which is better commented:
% Find out where the normalized cross correlation image is brightest.
[maxCorrValue, maxIndex] = max(abs(correlationOutput(:)));
[yPeak, xPeak] = ind2sub(size(correlationOutput),maxIndex(1))
% Because cross correlation increases the size of the image,
% we need to shift back to find out where it would be in the original image.
corr_offset = [(xPeak-size(smallSubImage,2)) (yPeak-size(smallSubImage,1))]
% Plot it over the original image.
subplot(2, 2, 4); % Re-display image in lower right.
imshow(rgbImage);
axis on; % Show tick marks giving pixels
hold on; % Don't allow rectangle to blow away image.
% Calculate the rectangle for the template box. Rect = [xLeft, yTop, widthInColumns, heightInRows]
boxRect = [corr_offset(1) corr_offset(2) templateWidth, templateHeight]
% Plot the box over the image.
rectangle('position', boxRect, 'edgecolor', 'g', 'linewidth',2);
% Give a caption above the image.
title('Template Image Found in Original Image', 'FontSize', fontSize);
uiwait(helpdlg('Done with demo!'));
EngStudent
on 7 Apr 2013
Edited: EngStudent
on 7 Apr 2013
thank you so much. so when you use the imcrop command does it create a new axis for the cropped image? Also are the corr_offset results from the cross correlation program in pixels?
How do i get the cross correlation program to give me the exact position of this image (saved in a tiff stack) in the code below. I have used the first frame as a template and I put this template out the for loop,I want the cross correlation program to detect the movement of the this image across the tiffstack and give me back the center co-ordinates i used to create this circle.
for k = 1:10
x=k;
y=50;
plot(x,y,'.','MarkerSize',200);
axis([-30,100,-30,100]);
if k==1
export_fig stack.tif
else
export_fig stack.tif -append
end
Just make xpeak and ypeak arrays.
How do I make the cross correlation program to detect really small displacement across many frames
What does 1 and 2 mean in size(sub_rgbImage,2) and size(sub_rgbImage,1) and also what does the rect_offset mean?
maxCorrValue, maxIndex] = max(abs(correlationOutput(:)))
[ypeak, xpeak] = ind2sub(size(correlationOutput),maxIndex(1))
corr_offset = [(xpeak-size(sub_rgbImage,2))
(ypeak-size(sub_rgbImage,1))]
%relative offset between position of subimages
rect_offset = [(rect_A(1)- rect_rgbImage(1))
(rect_A(2)- rect_rgbImage(2))]
%total offset
offset = corr_offset + rect_offset
xoffset= offset(1)
yoffset= offset(2)
More Answers (0)
Categories
Find more on Template Matching in Help Center and File Exchange
Products
See Also
on 2 Apr 2013
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)