1

私はMatlabと画像処理も初めてです。このような画像で背景と前景を分離する作業を行っています

パスポート画像青色の背景

私はこのような画像を何百枚も持っています。試行錯誤により、(RGB 空間で) しきい値を見つけました。赤のレイヤーは常に 150 未満であり、背景がある場所では緑と青のレイヤーは 150 を超えています。

したがって、私のRGB画像がIおよび私のr場合gbレイヤーは

redMatrix = I(:,:,1);
greenMatrix = I(:,:,2);
blueMatrix = I(:,:,3);

赤、緑、青の値が150より大きいか小さい座標を見つけることで、次のような背景の座標を取得できます

[r1 c1] = find(redMatrix < 150);
[r2 c2] = find(greenMatrix > 150);
[r3 c3] = find(blueMatrix > 150);

で何千ものピクセルの座標を取得するようになりましたr1,c1,r2,c2,r3 and c3

私の質問:

  1. 赤が 150 未満で、緑と青が 150 より大きいピクセルの座標など、一般的な値を見つける方法は? r1andのすべての座標を反復しc1、それらが発生するかどうかをr2 c2確認r3 c3し、それが共通点であることを確認する必要があります。しかし、それは非常に高価です。 これはループなしで実現できますか?

  2. [commonR commonC]どういうわけか、 andcommonRcommonCare both of order のような共通点を思いついた場合5000 X 1、 Image のこの背景ピクセルにアクセスするIには、最初にアクセスしてから、次commonRのようにcommonCimageにアクセスする必要がありますI

    I(commonR(i,1),commonC(i,1))

それも高価です。繰り返しますが、私の質問は、これをループなしで実行できるかということです。

どんな助けでも大歓迎です。

@Science_Fictionの回答で解決策を得ました

彼/彼女の答えを精緻化するだけです

使った

mask = I(:,:,1) < 150 & I(:,:,2) > 150 & I(:,:,3) > 150;
4

2 に答える 2

4

ループは必要ありません。あなたはこのようにそれを行うことができます:

I = imread('image.jpg');
redMatrix = I(:,:,1);
greenMatrix = I(:,:,2);
blueMatrix = I(:,:,3);
J(:,:,1) = redMatrix < 150;
J(:,:,2) = greenMatrix > 150;
J(:,:,3) = blueMatrix > 150;
J = 255 * uint8(J);
imshow(J);

画像

背景を分離するには、グレースケール画像でも十分です。

K = ((redMatrix < 150) + (greenMatrix > 150) + (blueMatrix > 150))/3;
imshow(K);

ここに画像の説明を入力してください

編集

あなたがリンクした他の画像も使って、私は別の見方をしました。背景色の違いを考えると、画像ヒストグラムをハードコーディングするのではなく、画像ヒストグラムからしきい値を導き出す方が良い結果が得られると思いました。

場合によっては、このアルゴリズムは少し厳密です。たとえば、衣服の一部を背景と一緒に消去します。しかし、画像の90%以上がかなりうまく分離されていると思います。これは、固定のしきい値で達成できるものよりも堅牢です。

close all;

path = 'C:\path\to\CUHK_training_cropped_photos\photos';
files = dir(path);
bins = 16;

for f = 3:numel(files)
    fprintf('%i/%i\n', f, numel(files));
    file = files(f);
    if isempty(strfind(file.name, 'jpg'))
        continue
    end

    I = imread([path filesep file.name]);

    % Take the histogram of the blue channel
    B = I(:,:,3);
    h = imhist(B, bins);
    h2 = h(bins/2:end);

    % Find the most common bin in the *upper half*
    % of the histogram 
    m = bins/2 + find(h2 == max(h2));

    % Set the threshold value somewhat below  
    % the value corresponding to that bin
    thr = m/bins - .25;
    BW = im2bw(B, thr);
    % Pad with ones to ensure background connectivity
    BW = padarray(BW, [1 1], 1);
    % Find connected regions in BW image
    CC = bwconncomp(BW);    
    L = labelmatrix(CC);
    % Crop back again
    L = L(2:end-1,2:end-1);

    % Set the largest region in the orignal image to white
    for c = 1:3
        channel = I(:,:,c);
        channel(L==1) = 255;
        I(:,:,c) = channel;
    end 

    % Show the results with a pause every 16 images    
    subplot(4,4,mod(f-3,16)+1);
    imshow(I);
    title(sprintf('Img %i, thr %.3f', f, thr));

    if mod(f-3,16)+1 == 16
        pause
        clf
    end    

end

pause
close all;

結果:

ここに画像の説明を入力してください

于 2013-01-20T10:50:16.057 に答える
3

あなたのアプローチは基本的ですがまともなようです。この特定の画像の場合、背景は主に青で構成されているため、粗雑にして次のことを行います。

mask = img(:,:,3) > 150;

これにより、150 を超える場合に true と評価されるピクセルが 0 に、false と評価されるピクセルが 1 に設定されます。ただし、白黒の画像が表示されます。

imshow(mask);

色を追加するには

mask3d(:,:,1) = mask; 
mask3d(:,:,2) = mask; 
mask3d(:,:,3) = mask;

img(mask3d) = 255;
imshow(img);

うまくいけば、真っ白な背景で顔のカラー画像が得られるはずです。これにはすべて、試行錯誤が必要です。

于 2013-01-20T10:52:45.007 に答える