问题
Is there an elegant way in Matlab to get the output of normxcorr2
cropped to the size of the image or cropped only to the part of the matrix that does not use zero padded edges in computation?
To understand what I mean, consider the conv2
command. There is an optional parameter called shape
that can be set to same
or valid
.
C = conv2(A,B,'same');
C = conv2(A,B,'valid');
For example:
size( conv2( rand(50,50) , rand(6,6), 'valid') )
ans =
45 45
size( conv2( rand(50,50) , rand(6,6), 'same') )
ans =
50 50
size( conv2( rand(50,50) , rand(6,6)) )
ans =
55 55
Currently I wrote my own function, that does something like this:
function I = normxcorr2e(template,im,shape)
switch shape
case 'same'
I = normxcorr2(template,im);
r = size(I,1)-size(im,1);
c = size(I,2)-size(im,2);
m1=floor(r/2);
n1=floor(c/2);
m2=ceil(r/2);
n2=ceil(c/2);
I(1:m2,:) = [];
I(end-m1+1:end,:) = [];
I(:,1:n2) = [];
I(:,end-n1+1:end) = [];
case 'full'
%Do nothing
case 'valid'
%TODO - write this case...
otherwise
throw(Mexception('normxcorr2e:BadInput','shape %s is not recognized',shape));
end
end
Do you have a better idea? The main criterion for a successful answer will be the elegance of the proposed solution.
Edit(1) First of all, thanks for all of your answers. All of them are good and upvoted by me. I still haven't decided which is the best. By the way, I am thinking recently about the case where the template is large compared to the image. In that case, it makes sense to speedup the computation by cropping the image
argument before running normxcorr2
.
回答1:
Here's a variant that has a few extra features relative to the other answers:
- It allows you to omit the shape argument (default is
'full'
). - It only calls normxcorr2 when
shape
is a valid string. - It performs the indexing in one line using logical indexing. The sizes of the lead padding and desired center region is used to create index vectors of true and false values. The trailing padding doesn't need to be specified since a logical index that is shorter than the dimension it indexes will simply be padded with false values.
And here's the code:
function I = normxcorr2e(template, im, shape)
if (nargin == 2) || strcmp(shape,'full')
I = normxcorr2(template, im);
return
end
switch shape
case 'same'
pad = floor(size(template)./2);
center = size(im);
case 'valid'
pad = size(template) - 1;
center = size(im) - pad;
otherwise
throw(Mexception('normxcorr2e:BadInput',...
'SHAPE must be ''full'', ''same'', or ''valid''.'));
end
I = normxcorr2(template, im);
I = I([false(1,pad(1)) true(1,center(1))], ...
[false(1,pad(2)) true(1,center(2))]);
end
回答2:
This would be much more concise. I hope it's what you're looking for:
function I = normxcorr2e(template,im,shape)
args={'full','same','valid'};
cropSize=(find(strcmp(shape,args))-1)*size(template);
crop=@(x,r) x(1+floor(r(1)/2):end-ceil(r(1)/2),1+floor(r(2)/2):end-ceil(r(2)/2))
I=crop(normxcorr2(template,im),cropSize);
回答3:
There is not much elegance here - you run the correlation, then you remove what you can't use. But it works.
function I = normxcorr2e(template,im,shape)
%# perform cross correlation with automated zero-padding
I = normxcorr2(template,im);
switch shape
case 'same'
%# if we were guaranteed to have odd-sized templates only
%# we would only need padLow
templateSize = size(template);
padLow = floor(templateSize/2);
padHigh = templateSize - padLow - 1;
I = I( (1+padLow(1)):(end-padHigh(1)), (1+padLow(2)):(end-padHigh(2)) );
case 'full'
%Do nothing
case 'valid'
%# with even size, we need to remove the larger of the two pad sizes
%# i.e. padLow, on all sides
templateSize = size(template);
padLow = templateSize/2;
I = I( (2*padLow(1)):(end-2*padLow(1)+1), (2*padLow(2)):(end-2*padLow(2)+1) );
otherwise
throw(Mexception('normxcorr2e:BadInput','shape %s is not recognized',shape));
end
来源:https://stackoverflow.com/questions/9145107/an-elegant-way-to-get-the-output-of-normxcorr2-in-a-manner-similar-to-conv2