7

LBL 알고리즘의 Matlab 구현이 here 인 것을 알기 위해 고민 중입니다. 나는 모든 픽셀에 대해 바이너리를 계산하는 방법을 찾고있다. 이웃 픽셀이 실제 중심 픽셀 크기보다 큰 부분을 계산합니다. 로컬 히스토그램을 사용하여 이미지의 피쳐를 계산하기 위해 모든 픽셀의 바이너리를 계산하고 싶습니다.로컬 바이너리 패턴을위한 MATLAB 코드

[ysize, xsize] = size(image); 

miny=min(spoints(:,1)); 
maxy=max(spoints(:,1)); 
minx=min(spoints(:,2)); 
maxx=max(spoints(:,2)); 

% Block size, each LBP code is computed within a block of size bsizey*bsizex 
bsizey=ceil(max(maxy,0))-floor(min(miny,0))+1; 
bsizex=ceil(max(maxx,0))-floor(min(minx,0))+1; 

% Coordinates of origin (0,0) in the block 
origy=1-floor(min(miny,0)); 
origx=1-floor(min(minx,0)); 

% Minimum allowed size for the input image depends 
% on the radius of the used LBP operator. 
if(xsize < bsizex || ysize < bsizey) 
    error('Too small input image. Should be at least (2*radius+1) x (2*radius+1)'); 
end 

% Calculate dx and dy; 
dx = xsize - bsizex; 
dy = ysize - bsizey; 

% Fill the center pixel matrix C. 
C = image(origy:origy+dy,origx:origx+dx); 
d_C = double(C); 

bins = 2^neighbors; 

% Initialize the result matrix with zeros. 
result=zeros(dy+1,dx+1); 

%Compute the LBP code image 
% the whole process here 
for i = 1:neighbors 
    y = spoints(i,1)+origy; 
    x = spoints(i,2)+origx; 
    % Calculate floors, ceils and rounds for the x and y. 
    fy = floor(y); cy = ceil(y); ry = round(y); 
    fx = floor(x); cx = ceil(x); rx = round(x); 
    % Check if interpolation is needed. 
    if (abs(x - rx) < 1e-6) && (abs(y - ry) < 1e-6) 
    % Interpolation is not needed, use original datatypes 
    N = image(ry:ry+dy,rx:rx+dx); 
    D = N >= C; 
    else 
    % Interpolation needed, use double type images 
    ty = y - fy; 
    tx = x - fx; 

    % Calculate the interpolation weights. 
    w1 = roundn((1 - tx) * (1 - ty),-6); 
    w2 = roundn(tx * (1 - ty),-6); 
    w3 = roundn((1 - tx) * ty,-6) ; 
    % w4 = roundn(tx * ty,-6) ; 
    w4 = roundn(1 - w1 - w2 - w3, -6); 

    % Compute interpolated pixel values 
    N = w1*d_image(fy:fy+dy,fx:fx+dx) + w2*d_image(fy:fy+dy,cx:cx+dx) + ... 
w3*d_image(cy:cy+dy,fx:fx+dx) + w4*d_image(cy:cy+dy,cx:cx+dx); 
    N = roundn(N,-4); 
    D = N >= d_C; 
end 
    % Update the result matrix. 
    v = 2^(i-1); 
    result = result + v*D; 
end 

%Apply mapping if it is defined 
if isstruct(mapping) 
bins = mapping.num; 
for i = 1:size(result,1) 
    for j = 1:size(result,2) 
     result(i,j) = mapping.table(result(i,j)+1); 
    end 
    end 
end 

if (strcmp(mode,'h') || strcmp(mode,'hist') || strcmp(mode,'nh')) 
    % Return with LBP histogram if mode equals 'hist'. 
    result=hist(result(:),0:(bins-1)); 
    if (strcmp(mode,'nh')) 
    result=result/sum(result); 
    end 
else 
%Otherwise return a matrix of unsigned integers 
if ((bins-1)<=intmax('uint8')) 
    result=uint8(result); 
elseif ((bins-1)<=intmax('uint16')) 
    result=uint16(result); 
else 
    result=uint32(result); 
end 
end 
size(result) 
end 

반복적으로 모든 픽셀의 8 개 이웃에 대해 결과에 일부 값을 추가합니다. 그러나 LBP 바이너리와 어떻게 관련이 있습니까? 다음과 같은 C++ LBP 접근 방식에 대해 다음 코드와 상관 관계가되는 방법 :

uchar lbp(const Mat_<uchar> & img, int x, int y) 
{ 
    // this is pretty much the same what you already got.. 
    uchar v = 0; 
    uchar c = img(y,x); 
    v += (img(y-1,x ) > c) << 0; 
    v += (img(y-1,x+1) > c) << 1; 
    v += (img(y ,x+1) > c) << 2; 
    v += (img(y+1,x+1) > c) << 3; 
    v += (img(y+1,x ) > c) << 4; 
    v += (img(y+1,x-1) > c) << 5; 
    v += (img(y ,x-1) > c) << 6; 
    v += (img(y-1,x-1) > c) << 7; 
    return v; 

}

+0

코드의 일부만 표시됩니다. 관련 코드 전체를 게시하고 올바르게 들여 쓰기를하십시오. – Shai

답변

7

그것은 matlab에 오히려 적합 LBP의 벡터화 구현입니다.

초기화 지침 다음에 "for i = 1:neighbors"줄에서 시작하는 메인 루프를 살펴 보겠습니다. 루프는 매우 명확합니다. 하나의 이웃과 중심 픽셀의 비교를 계산하고 루프가 모든 이웃을 반복합니다. 이 점을 알고 있으므로 루프에 깊이 들어가서 모든 결과가 누적되는 방식을 이해하십시오.

대략적인 정수 원 대신 실제 원을 고려하기 때문에 루프의 핵심은 실제로 복잡합니다. 따라서 명령의 주요 부분의 목적은 인접 픽셀의 보간 된 강도를 계산하는 것입니다. 여기서는 참조 용으로 가지고있는 C++ 코드와 다릅니다. 여기서는 1 픽셀 너비의 정수 원형 만 사용합니다. lbp.m 코드를 사용하면 이론적으로 LBP를 반경 R의 원을 따라 N 개의 샘플링 포인트로 계산할 수 있으므로 C++은 반경 1의 원과 8 개의 샘플링에 해당합니다. 포인트, 보간이 없다면. 그러나 (abs(x - rx) < 1e-6) && (abs(y - ry) < 1e-6)이 거짓 일 때 이웃이 이미지의 픽셀 격자에 맞지 않을 때 보간법이 있습니다.

(abs(x - rx) < 1e-6) && (abs(y - ry) < 1e-6)이 참이면 보간이 없으므로 중앙 픽셀과 현재 이웃 사이의 모든 비교 계산이 D에 직접 저장됩니다. 그렇지 않으면, 전체 이미지에 대해 샘플링 인접점에서 강도의 쌍 선형 보간을 계산합니다 : N = w1*d_image(fy:fy+dy,fx:fx+dx) + w2*d_image(fy:fy+dy,cx:cx+dx) + w3*d_image(cy:cy+dy,fx:fx+dx) + w4*d_image(cy:cy+dy,cx:cx+dx);.

그리고 마지막으로 업데이트 부분 인 v = 2^(i-1); result = result + v*D;으로 넘어갑니다. v은 shift와 동일합니다. i 번째 이웃에 대해 비교 값을 i-1으로 왼쪽으로 이동하거나 동등하게 곱하면 2^(i-1)이됩니다. 그런 다음 result의 합계입니다. 따라서 루프가 끝날 때 계산은 실제로 하나의 픽셀 대신 전체 이미지에서 수행된다는 점을 제외하고는 C++ 코드와 동일합니다. 그리고 C++ 코드는 반경 1 및 8 샘플링 포인트의 인접 원과 함께 matlab 루프의 풀리지 않은 버전으로 볼 수 있습니다. 이 시점에서 LBP 맵이 계산됩니다. 다음 블록은 LBP 맵의 추가 처리입니다 (맵핑 테이블을 통해 맵핑하고 선택적으로 LBP 이미지 자체 대신 LBP 이미지의 막대 그래프를 계산합니다).

이제 전체 스크립트에 대해 약간의 토론을하십시오. 여기 스크립트의 끝 부분에 숨겨진 결함이 있습니다. 사실, 코드를 통해 LBP 이미지가 int32으로 캐스팅되므로 결국 32 개 이웃으로 제한됩니다. 더 이상은 아닙니다. 결함은 변수 result이 정수 행렬이 아닌 이중 행렬로 할당된다는 것입니다. 따라서 result 이상을 LBP에서 비트를 변경하는 정수로 캐스팅 할 때 업데이트 할 때 근사 문제가 없기를 바랍니다. 일반적으로 최소 52 비트의 정밀도 비트가 있어야합니다 (IEEE 754 사양의 경우 wikipedia에 따라). 여기 위험한 것 같아.그리고 반대로 나는 고정 된 크기의 효율적인 비트 벡터를위한 matlab 타입을 알지 못한다. int32 대신 int64을 사용 하겠지만 64 개의 이웃 샘플링에 한계가 있습니다.

EDIT 이제

당신의 소원은 3 * 3 지역에 제한된 일부 지역의 바이너리 패턴을 commpute하는 경우,이 matlab에 기능이 방법은 당신을 위해 너무 일반적이며, 가장 좋은 점은 루프를 풀다하는 것입니다 그래서이 C++ 코드에 정말 가깝습니다.

result = uint8(ysize, xsize); 
result = (image(1:end-2,2:end-1) > image(2:end-1,2:end-1));         % <=> v += (img(y-1,x ) > c) << 0; 
result = result|bitshift((image(1:end-2,3:end) > image(2:end-1,2:end-1)), 1, 'uint8');  % <=> v += (img(y-1,x+1) > c) << 1; 
result = result|bitshift((image(2:end-1,3:end) > image(2:end-1,2:end-1)), 2, 'uint8');  % <=> v += (img(y ,x+1) > c) << 2; 
result = result|bitshift((image(3:end,3:end) > image(2:end-1,2:end-1)), 3, 'uint8');  % <=> v += (img(y+1,x+1) > c) << 3; 
result = result|bitshift((image(3:end,2:end-1) > image(2:end-1,2:end-1)), 4, 'uint8');  % <=> v += (img(y+1,x ) > c) << 4; 
result = result|bitshift((image(3:end,1:end-2) > image(2:end-1,2:end-1)), 5, 'uint8');  % <=> v += (img(y+1,x-1) > c) << 5; 
result = result|bitshift((image(2:end-1,3:end) > image(2:end-1,2:end-1)), 6, 'uint8');  % <=> v += (img(y ,x-1) > c) << 6; 
result = result|bitshift((image(1:end-2,1:end-2) > image(2:end-1,2:end-1)), 7, 'uint8'); % <=> v += (img(y-1,x-1) > c) << 7; 

그것은 강력한 벡터화를 사용하여, 매트랩 스크립트에 C 코드의 정확한 번역입니다 : 여기에 대한 코드 조각 (나는 비트 또는 대신에 추가로 사용할 수 있지만 그것은 상당의)입니다. 이것으로 손쉽게 다른 주문이나이 근처의 다른 테스트를 변경하는 것이 간단합니다. MATLAB 스크립트에 오류가 있기 때문에이 지점을 언급합니다. 53 행에는 잘못된 기호가 있습니다. 인접성은 spoints=[-1 -1; -1 0; -1 1; 0 -1; -0 1; 1 -1; 1 0; 1 1]; 대신 spoints=[-1 -1; -1 0; -1 1; 0 -1; 0 -1; 1 -1; 1 0; 1 1];으로 더 좋습니다.

+0

꽤 깨끗합니다. 내가하고 싶습니다 코드를 변경하는 것입니다. 중앙 픽셀에 대한 모든 이웃 픽셀의 원 비교 대신 픽셀을 향해 비교하는 LGP 접근법을 사용하여 비교를 변경합니다. C++에서는 함수 v + = (img (y-1, x)> c) << 0;의 라인을 변경해야합니다. (중심 픽셀의 픽셀을 향한 비교가 필요합니다) . 어떻게하면 MATLAB 코드에서 동일한 작업을 수행 할 수 있습니다. –

+0

@FereRes 당신은 로컬 그라디언트 패턴에 대해 이야기하고 있습니까? 그 점을 분명하게하기 위해 OP를 편집 해 주실 수 있습니까? (참조로 좋을 것입니다). 나는이 기사 [http://www.academia.edu/4876261/Local_Gradient_Pattern_-AA_Novel_Feature_Representation_for_Facial_Expression_Recognition]을 따라 대답을 편집한다. – Bentoy13

+0

좋아, 나는 기본적으로 LBP에서 다음 코드로 바꿀 수 있기 위해 기본적으로 C++과 matlab 코드를 모두 이해하고자한다. 비교에서 단 하나의 수정 인 LGB. (나는 r = 1과 8 이웃의 단순한 경우를 이야기하고있다). LGP에 대한 나의 언급은 http://ac.els-cdn.com/S0031320312001094/1-s2.0-S0031320312001094-main.pdf?_tid=c52c9234-7960-11e4-9b66-00000aacb35e&acdnat=1417441906_2c6ff3b2b2339ca7ebe5e1ea57be796a –

7

로컬 바이너리 패턴에 관한 나의 마지막 프로젝트를 마쳤습니다. 내가 가리킨 코드를 보았지만 스스로 코드를 작성하기로 결정했습니다.

function [ LBP ] = LBP(I2) 
m=size(I2,1); 
n=size(I2,2); 
for i=2:m-1 
    for j=2:n-1 
     J0=I2(i,j); 
     I3(i-1,j-1)=I2(i-1,j-1)>J0; 
     I3(i-1,j)=I2(i-1,j)>J0; 
     I3(i-1,j+1)=I2(i-1,j+1)>J0; 
     I3(i,j+1)=I2(i,j+1)>J0; 
     I3(i+1,j+1)=I2(i+1,j+1)>J0; 
     I3(i+1,j)=I2(i+1,j)>J0; 
     I3(i+1,j-1)=I2(i+1,j-1)>J0; 
     I3(i,j-1)=I2(i,j-1)>J0; 
     LBP(i,j)=I3(i-1,j-1)*2^7+I3(i-1,j)*2^6+I3(i-1,j+1)*2^5+I3(i,j+1)*2^4+I3(i+1,j+1)*2^3+I3(i+1,j)*2^2+I3(i+1,j-1)*2^1+I3(i,j-1)*2^0; 
    end 
end 
end 

I2 당신이 통과하고, LBP가 출력되는 이미지 :

이 내 코드입니다. 로컬 바이너리 패턴 : http://quantgreeks.com/local-binary-pattern-in-matlab/에 이것을 썼습니다. 나는 더 효율적인 형태로 코드를 작성할 수 있다는 것을 알고있다. 그러나이 방법으로 작성하면 로컬 바이너리 패턴이 어떻게 작동하는지 명확히 알 수 있습니다.