분리 가능한 정수 2D 필터 계수를 분해하는 빠르고 효율적인 방법


21

주어진 정수 계수의 2D 커널을 정수 계수를 가진 두 개의 1D 커널로 분리 할 수 ​​있는지 여부를 신속하게 결정하고 싶습니다. 예 :

 2   3   2
 4   6   4
 2   3   2

분리 가능하다

 2   3   2

 1
 2
 1

분리성에 대한 실제 테스트는 정수 산술을 사용하여 매우 간단 해 보이지만 정수 계수를 사용하여 1D 필터로 분해하는 것이 더 어려운 문제로 판명되었습니다. 어려운 점은 행 또는 열 사이의 비율이 정수가 아닌 것일 수 있다는 사실에 있습니다. 예를 들어 위의 예에서 우리는 2, 1/2, 3/2 및 2/3의 비율을 가지고 있습니다.

SVD와 같은 헤비 듀티 접근법을 실제로 사용하고 싶지 않습니다 .a) 내 요구에 비해 계산 비용이 비교적 비싸고 (b) 정수 계수 를 결정하는 데 여전히 도움이되는 것은 아닙니다 .

어떤 아이디어?


추가 정보

계수는 양수, 음수 또는 0 일 수 있으며, 1D 벡터 중 하나 또는 둘 다의 합이 0 인 병리학 적 사례가있을 수 있습니다. 예 :

-1   2  -1
 0   0   0
 1  -2   1

분리 가능하다

 1  -2   1

-1
 0
 1

1
나는 대학에서 이것을 다시 알아 내려고 노력했던 것을 기억합니다. 나는 거의 성공했지만 방법을 기억하지 못한다. =) 나는 당신이 그것을 언급 한 지금 그것에 대해 생각을 멈출 수 없습니다!
Phonon

@Phonon : 흠-계속 생각하십시오-이것에 대한 영감을 줄 수 있습니다. ;-)
Paul R

double 또는 float 값에 대해 동일한 작업을 수행 할 수 있습니까?
Diego Catalano

@ DiegoCatalano : 아래 Denis의 대답과 그가 math.stackexchange.com에서 연결하는 질문을 참조하십시오. 부정 소수점 계수의 경우보다 일반적인 경우에 효과적이라고 생각합니다.
Paul R

@PaulR, 어떻게 이메일로 연락 할 수 있습니까? 고맙습니다.
Royi

답변:


11

나는 @Phonon대답을 취하고 다소 수정하여 행 / 열 합계가 아닌 맨 위 행과 왼쪽 열에서 GCD 접근 방식을 사용합니다. 이것은 병리학 적 사례를 조금 더 잘 처리하는 것으로 보입니다. 맨 위 행 또는 왼쪽 열이 모두 0 인 경우에도 여전히 실패 할 수 있지만이 방법을 적용하기 전에 이러한 경우를 확인할 수 있습니다.

function [X, Y, valid] = separate(M)    % separate 2D kernel M into X and Y vectors 
  X = M(1, :);                          % init X = top row of M
  Y = M(:, 1);                          % init Y = left column of M
  nx = numel(X);                        % nx = no of columns in M
  ny = numel(Y);                        % ny = no of rows in M
  gx = X(1);                            % gx = GCD of top row
  for i = 2:nx
    gx = gcd(gx, X(i));
  end
  gy = Y(1);                            % gy = GCD of left column
  for i = 2:ny
    gy = gcd(gy, Y(i));
  end
  X = X / gx;                           % scale X by GCD of X
  Y = Y / gy;                           % scale Y by GCD of Y
  scale = M(1, 1) / (X(1) * Y(1));      % calculate scale factor
  X = X * scale;                        % apply scale factor to X
  valid = all(all((M == Y * X)));       % result valid if we get back our original M
end

에 많은 감사 @Phonon@Jason R이에 대한 원래의 아이디어.


10

알았다! MATLAB 코드를 게시하면 오늘 밤 또는 내일 설명이 게시됩니다.

% Two original arrays
N = 3;
range = 800;
a = round( range*(rand(N,1)-0.5) )
b = round( range*(rand(1,N)-0.5) )

% Create a matrix;
M = a*b;
N = size(M,1);

% Sanity check
disp([num2str(rank(M)) ' <- this should be 1!']);

% Sum across rows and columns
Sa = M * ones(N,1);
Sb = ones(1,N) * M;

% Get rid of zeros
SSa = Sa( Sa~=0 );
SSb = Sb( Sb~=0 );

if isempty(SSa) | isempty(SSb)
    break;
end

% Sizes of array without zeros
Na = numel(SSa);
Nb = numel(SSb);

% Find Greatest Common Divisor of Sa and Sb.
Ga = SSa(1);
Gb = SSb(1);

for l=2:Na
    Ga = gcd(Ga,SSa(l));
end

for l=2:Nb
    Gb = gcd(Gb,SSb(l));
end

%Divide by the greatest common divisor
Sa = Sa / Ga;
Sb = Sb / Gb;

%Scale one of the vectors
MM = Sa * Sb;
Sa = Sa * (MM(1) / M(1));

disp('Two arrays found:')
Sa
Sb
disp('Sa * Sb = ');
Sa*Sb
disp('Original = ');
M

고마워-이것은 대단합니다-지난 밤에 계수 등을 분해하는 것에 대해 생각하고 있었지만 GCD를 사용하는 것이 훨씬 간단하고 우아합니다. 불행히도 철분을 제거하는 데 여전히 하나의 주름이 있습니다. 양수 및 음수 계수 모두에서 작동해야하며, 예를 들어 변성 사례가 발생할 수 있습니다 A=[-2 1 0 -1 2]; B=[2 -3 6 0 -1]; M=A'*B;. 여기서 문제는 sum(A) = 0그렇게 하는 것 Sb = [0 0 0 0 0]입니다. 계수 의 절대 값의 합을 사용하고 알고리즘 이 도움이되는지 알고리즘을 수정하려고합니다 . 도와 주셔서 감사합니다.
Paul R

OK - 여전히 GCDs을 얻을 사용하여 스케일링을 할 수있는 것 같습니다 abs(M), 즉 Sa=abs(M)*ones(N,1); Sb=ones(1,N)*abs(M);다음과 같은 이상 계속,하지만 난 아직 표지판을 복원하는 방법을 볼 수 없습니다 Sa, Sb마지막에. 위의 원래 질문에서 문제를 설명하는 병리학 예제를 추가했습니다.
Paul R

나는 지금 해결책을 가지고 있다고 생각합니다-나는 그것을 별도의 답변으로 게시했지만 기본 아이디어에 대한 크레딧은 당신에게갑니다. 다시 감사합니다!
Paul R

7

어쩌면 나는 문제를 사소하게 만들고 있지만 아마도 당신이 할 수있는 것처럼 보입니다.

  • NMAaii=0,1,,N1
  • j>0

    • aja0jrj
    • rj
    • rjaja0j0x
    • aja0
  • x

xk,norm=xkmini=0N1xi
  • xnorm
    xscaled=Kxnorm,K=1,2,,M
    KM

가장 우아한 방법은 아니지만 더 좋은 방법이있을 수 있지만 작동해야하고 구현하기가 매우 간단하며 적당한 크기의 행렬의 경우 비교적 빠릅니다.


감사합니다-세부 사항에 푹 빠지기 전에 아마도이 방향으로 향하고 있다고 생각합니다. 이 방법을 사용하여 항상 솔루션에 도달한다는 것은 100 % 명확하지 않지만 어쨌든이 코드를 작성하고 몇 가지 예제로 시도해야합니다. 나는 "가장 좋은"솔루션을 산출하기 위해 행 방향과 열 방향으로 적용해야 할 수도 있습니다. 시간을내어 자세한 내용을 알려 주셔서 감사합니다. 바쁘게 처리하고 작동 방식을 알려 드리겠습니다.
Paul R

행의 첫 번째 요소에 대한 최대 공약수를 찾지 못하고이를 사용하여 기본 벡터를 결정할 수 없습니까?
Jim Clay

@JimClay : 그렇습니다. 기능을 사용할 수 있다면 결국에는 실제로하는 일입니다.
Jason R

3

xyzA|Axyz|
x y z
yzxx y z x y z ... 차례로.

( math.stackexchange의 대략적인 컨볼 루션 에서 분리 가능한 컨볼 루션 으로 볼 수 있습니다.)


1
설명 할 수없는 링크로 질문에 대답하지 마십시오. 답에 필요한 세부 사항을 설명하고 참조 용 링크 만 포함하는 것이 좋습니다. 링크가 끊어 지더라도 대답의 필수 세부 사항은 여전히 ​​있습니다.
Sam Maloney

@ SamMaloney : 왜 필요한지 알 수 없습니다. 링크는 모든 것을 자세히 설명합니다. Q & A 검색에서 여전히 팝업됩니다. 그래서 왜 안돼?
Naresh

1
@Naresh 스택 교환 사이트의 목표 중 하나는 향후 참조를 위해 답변 된 질문의 저장소를 구축하는 것이므로 언급 만합니다. 따라서이 특정 링크가 다른 SE 사이트에 대한 것이므로 상당히 안전해야한다는 것을 이해하지만 몇 년이 지난 지금도 여전히 링크를 사용하지 않는 것이 가장 좋습니다. 답변에 이러한 "두 가지 쉬운 방법"에 대한 일반적인 개요를 제공하면 연결된 질문에 문제가 발생하더라도 정보가 유지 될 수 있습니다.
Sam Maloney
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.