web-dev-qa-db-ja.com

MATLABの最近傍内挿アルゴリズム

最近傍内挿アルゴリズムを使用して、入力画像を拡大する独自の関数を記述しようとしています。悪い点は、それがどのように機能するかを見ることができるが、アルゴリズム自体を見つけることができないことです。私はどんな助けにも感謝します。

入力画像を2倍に拡大するために私が試したのは次のとおりです。

function output = nearest(input)
[x,y]=size(input);
output = repmat(uint8(0),x*2,y*2);
[newwidth,newheight]=size(output);
for i=1:y
    for j=1:x
        xloc = round ((j * (newwidth+1)) / (x+1));
        yloc = round ((i * (newheight+1)) / (y+1));
        output(xloc,yloc) = input(j,i);
    end
end

これが Mark の提案後の出力です alt text

20
Hellnar

しばらく前に、 MATLAB Image Processing Toolboximresize 関数のコードを調べて、画像の最近傍内挿の単純化バージョンを作成しました。これがあなたの問題にどのように適用されるかです:

_%# Initializations:

scale = [2 2];              %# The resolution scale factors: [rows columns]
oldSize = size(inputImage);                   %# Get the size of your image
newSize = max(floor(scale.*oldSize(1:2)),1);  %# Compute the new image size

%# Compute an upsampled set of indices:

rowIndex = min(round(((1:newSize(1))-0.5)./scale(1)+0.5),oldSize(1));
colIndex = min(round(((1:newSize(2))-0.5)./scale(2)+0.5),oldSize(2));

%# Index old image to get new image:

outputImage = inputImage(rowIndex,colIndex,:);
_

別のオプションは、組み込みの _interp2_ 関数を使用することですが、コメントの1つで組み込み関数を使用したくないと述べました。

編集:説明

誰かが興味を持っている場合、私は上の解決策がどのように機能するかを説明したいと思いました...

_newSize = max(floor(scale.*oldSize(1:2)),1);
_

まず、新しい行と列のサイズを取得するには、古い行と列のサイズにスケールファクターを掛けます。この結果は、 floor を使用して最も近い整数に切り捨てられます。スケールファクターが1未満の場合、サイズ値の1つが0の奇妙なケースになる可能性があります。これが max への呼び出しが少ないものを置き換えるために存在する理由です1よりも1よりも。

_rowIndex = min(round(((1:newSize(1))-0.5)./scale(1)+0.5),oldSize(1));
colIndex = min(round(((1:newSize(2))-0.5)./scale(2)+0.5),oldSize(2));
_

次に、行と列の両方に対して新しいインデックスのセットが計算されます。最初に、アップサンプリングされた画像のインデックスのセットが計算されます:1:newSize(...)。各イメージピクセルは、ピクセル1が0から1までの範囲、ピクセル2が1から2までの範囲など、特定の幅を持っていると見なされます。したがって、ピクセルの「座標」は中心として扱われるため、0.5になります。インデックスから差し引かれます。次に、これらの座標をスケール係数で割って、元の画像のピクセル中心座標のセットを作成します。これらの座標に0.5を加え、四捨五入して、元の画像の整数インデックスのセットを取得します。 min を呼び出すと、これらのインデックスが元の画像サイズoldSize(...)より大きくならないことが保証されます。

_outputImage = inputImage(rowIndex,colIndex,:);
_

最後に、元の画像にインデックスを付けるだけで、新しいアップサンプリングされた画像が作成されます。

19
gnovice

この答えは、簡潔で効率的であるよりも説明的です。その点では gnovice の解決策が最良だと思います。それがどのように機能するかを理解しようとしている場合は、読み続けてください...

コードの問題は、入力画像から出力画像に場所をマッピングすることです。これが、spotty出力を取得する理由です。入力画像がすべて白で、出力が黒に初期化される例を考えてみます。次のようになります。

screenshot

あなたがしなければならないことは反対です(出力から入力へ)。説明のために、次の表記法を検討してください。

1           c         1                 scaleC*c
+-----------+ 1       +----------------------+ 1
|    |      |         |        |             |
|----o      |   <===  |        |             |
|  (ii,jj)  |         |--------o             |
+-----------+ r       |      (i,j)           |
  inputImage          |                      |
                      |                      |
                      +----------------------+ scaleR*r
                            ouputImage

Note: I am using matrix notation (row/col), so:
  i ranges on [1,scaleR*r] , and j on [1,scaleC*c]
  and ii on [1,r], jj on [1,c]

アイデアは、場所ごとに(i,j)出力画像で、入力画像座標の「最も近い」場所にマッピングします。これは単純なマッピングなので、与えられたxyにマッピングする式を使用します(他のすべてのパラメーターが与えられます):

 x-minX      y-minY
--------- = ---------
maxX-minX   maxY-minY

この場合、xi/j座標であり、yii/jj座標です。したがって、それぞれを代入すると、次のようになります。

jj = (j-1)*(c-1)/(scaleC*c-1) + 1
ii = (i-1)*(r-1)/(scaleR*r-1) + 1

ピースを組み合わせると、次のコードが得られます。

% read a sample image
inputI = imread('coins.png');
[r,c] = size(inputI);
scale = [2 2];        % you could scale each dimension differently

outputI = zeros(scale(1)*r,scale(2)*c, class(inputI));

for i=1:scale(1)*r
    for j=1:scale(2)*c
        % map from output image location to input image location
        ii = round( (i-1)*(r-1)/(scale(1)*r-1)+1 );
        jj = round( (j-1)*(c-1)/(scale(2)*c-1)+1 );

        % assign value
        outputI(i,j) = inputI(ii,jj);
    end
end

figure(1), imshow(inputI)
figure(2), imshow(outputI)
20
Amro

MATLABはすでにそれを行っています。 imresize を使用:

output = imresize(input,size(input)*2,'nearest');

または、xとyの両方を均等にスケーリングする場合は、

output = imresize(input,2,'nearest');
2
Jacob

Xlocとylocを計算するには、より一般化された式が必要です。

xloc = (j * (newwidth+1)) / (x+1);
yloc = (i * (newheight+1)) / (y+1);

これは、変数に乗算結果に十分な範囲があることを前提としています。

0
Mark Ransom