matlab - images - Una forma elegante de obtener la salida de `normxcorr2` de manera similar a ''conv2''-(eliminando los bordes no deseados)
cross correlation python (3)
No hay mucha elegancia aquí: ejecuta la correlación, luego elimina lo que no puede usar. Pero funciona.
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
¿Existe una forma elegante en Matlab de obtener la producción de normxcorr2
recortada al tamaño de la imagen o recortada solo en la parte de la matriz que no utiliza bordes acolchados cero en el cálculo?
Para entender lo que quiero decir, considere el comando conv2
. Hay un parámetro opcional llamado shape
que puede establecerse en el same
o valid
.
C = conv2(A,B,''same'');
C = conv2(A,B,''valid'');
Por ejemplo:
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
Actualmente escribí mi propia función, que hace algo como esto:
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
Tienes una mejor idea? El criterio principal para una respuesta exitosa será la elegancia de la solución propuesta.
Editar (1) Antes que nada, gracias por todas sus respuestas. Todos ellos son buenos y han sido votados por mí. Todavía no he decidido cuál es el mejor. Por cierto, estoy pensando recientemente en el caso en que la plantilla es grande en comparación con la imagen. En ese caso, tiene sentido acelerar el cálculo recortando el argumento de la image
antes de ejecutar normxcorr2
.
Aquí hay una variante que tiene algunas características adicionales en relación con las otras respuestas:
- Le permite omitir el argumento de forma (el valor predeterminado es
''full''
). - Solo llama a
normxcorr2
cuando lashape
es una cadena válida. - Realiza la indexación en una línea usando indexación lógica . Los tamaños del relleno de relleno y la región central deseada se utilizan para crear vectores de índice de valores verdaderos y falsos. No es necesario especificar el relleno final, ya que un índice lógico que es más corto que la dimensión que indexa simplemente se rellenará con valores falsos.
Y aquí está el código:
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
Esto sería mucho más conciso. Espero que sea lo que estás buscando:
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);