Pregunta

Actualmente estoy trabajando en escribir una versión de MATLAB. Accesorios de región función para Octava GNU.He implementado la mayor parte, pero todavía estoy luchando con la implementación de algunas partes.Yo tenía preguntado previamente acerca de segundos momentos centrales de una región.

Esto fue útil en teoría, pero tengo problemas para implementar las sugerencias.Obtengo resultados muy diferentes a los de MATLAB (o al sentido común) y realmente no entiendo por qué.

Considere esta imagen de prueba:

Slanting ellipse.

Podemos verlo inclinado a 45 grados del eje X, con ejes menor y mayor de 30 y 100 respectivamente.

Ejecutándolo a través de MATLAB RegionProps La función confirma esto:

MajorAxisLength: 101.3362
MinorAxisLength: 32.2961
Eccentricity: 0.9479
Orientation: -44.9480

Mientras tanto, ni siquiera acierto con los ejes.estoy tratando de usar estas fórmulas de Wikipedia.

Mi código hasta ahora es:

momentos_raw.m:

function outmom = raw_moments(im,i,j)

  total = 0;
  total = int32(total);
  im = int32(im);

  [height,width] = size(im);

  for x = 1:width;
     for y = 1:height;
        amount = (x ** i) * (y ** j) * im(y,x);
        total = total + amount;
     end;
  end;

  outmom = total;

momentos_central.m:

function cmom = central_moments(im,p,q);

  total = 0;
  total = double(total);
  im = int32(im);

  rawm00 = raw_moments(im,0,0);

  xbar = double(raw_moments(im,1,0)) / double(rawm00);
  ybar = double(raw_moments(im,0,1)) / double(rawm00);

  [height,width] = size(im);

  for x = 1:width;
    for y = 1:height;
      amount = ((x - xbar) ** p) *  ((y - ybar) ** q) * double(im(y,x));
      total = total + double(amount);
    end;
  end;

  cmom = double(total);

Y aquí está mi código intentando usarlos.Incluyo comentarios para los valores que obtengo en cada paso:

inim = logical(imread('135deg100by30ell.png'));

cm00 = central_moments(inim,0,0);          % 2567

up20 = central_moments(inim,2,0) / cm00;   % 353.94
up02 = central_moments(inim,0,2) / cm00;   % 352.89
up11 = central_moments(inim,1,1) / cm00;   % 288.31

covmat = [up20, up11; up11, up02];
%[ 353.94  288.31
%  288.31  352.89 ]

eigvals = eig(covmat);          % [65.106 641.730]

minoraxislength = eigvals(1);   % 65.106
majoraxislength = eigvals(2);   % 641.730

No estoy seguro de qué estoy haciendo mal.Parece que estoy siguiendo esas fórmulas correctamente, pero mis resultados no tienen sentido.No he encontrado ningún error obvio en mis funciones de momento, aunque honestamente, para empezar, mi comprensión de los momentos no es la mejor.

¿Alguien puede ver dónde me estoy desviando?Muchas gracias.

¿Fue útil?

Solución

EDITAR:

De acuerdo a Wikipedia:

los valores propios [...] son proporcionala la longitud al cuadrado de los ejes del vector propio.

lo cual se explica por:

axisLength = 4 * sqrt(eigenValue)

A continuación se muestra mi versión del código (vectoricé las funciones de momentos):

my_regionprops.m

function props = my_regionprops(im)
    cm00 = central_moments(im, 0, 0);
    up20 = central_moments(im, 2, 0) / cm00;
    up02 = central_moments(im, 0, 2) / cm00;
    up11 = central_moments(im, 1, 1) / cm00;

    covMat = [up20 up11 ; up11 up02];
    [V,D] = eig( covMat );
    [D,order] = sort(diag(D), 'descend');        %# sort cols high to low
    V = V(:,order);

    %# D(1) = (up20+up02)/2 + sqrt(4*up11^2 + (up20-up02)^2)/2;
    %# D(2) = (up20+up02)/2 - sqrt(4*up11^2 + (up20-up02)^2)/2;

    props = struct();
    props.MajorAxisLength = 4*sqrt(D(1));
    props.MinorAxisLength = 4*sqrt(D(2));
    props.Eccentricity = sqrt(1 - D(2)/D(1));
    %# props.Orientation = -atan(V(2,1)/V(1,1)) * (180/pi);      %# sign?
    props.Orientation = -atan(2*up11/(up20-up02))/2 * (180/pi);
end

function cmom = central_moments(im,i,j)
    rawm00 = raw_moments(im,0,0);
    centroids = [raw_moments(im,1,0)/rawm00 , raw_moments(im,0,1)/rawm00];
    cmom = sum(sum( (([1:size(im,1)]-centroids(2))'.^j * ...
                     ([1:size(im,2)]-centroids(1)).^i) .* im ));
end

function outmom = raw_moments(im,i,j)
    outmom = sum(sum( ((1:size(im,1))'.^j * (1:size(im,2)).^i) .* im ));
end

...y el código para probarlo:

prueba.m

I = imread('135deg100by30ell.png');
I = logical(I);

>> p = regionprops(I, {'Eccentricity' 'MajorAxisLength' 'MinorAxisLength' 'Orientation'})
p = 
    MajorAxisLength: 101.34
    MinorAxisLength: 32.296
       Eccentricity: 0.94785
        Orientation: -44.948

>> props = my_regionprops(I)
props = 
    MajorAxisLength: 101.33
    MinorAxisLength: 32.275
       Eccentricity: 0.94792
        Orientation: -44.948

%# these values are by hand only ;)
subplot(121), imshow(I), imdistline(gca, [17 88],[9 82]);
subplot(122), imshow(I), imdistline(gca, [43 67],[59 37]);

screenshot

Otros consejos

¿Estás seguro del núcleo de tu raw_moments ¿función? Podrías intentar

amount = ((x-1) ** i) * ((y-1) ** j) * im(y,x);

Esto no parece suficiente para causar los problemas que está viendo, pero podría ser al menos una parte.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top