20

最近隣内挿アルゴリズムを使用して、入力画像をスケールアップするための独自の関数を作成しようとしています。悪い部分は、それがどのように機能するかを見ることができますが、アルゴリズム自体を見つけることができないことです。どんな助けにも感謝します。

これが、入力画像を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

これがマークの提案後の出力です代替テキスト

4

4 に答える 4

20

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

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

スクリーンショット

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

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)、出力画像の各場所について、入力画像座標の「最も近い」場所にマップすることです。これは単純なマッピングであるため、 (他のすべてのパラメーターが与えられた場合xに)与えられたものをマップする式を使用します。y

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

この場合、xi/j座標でyあり、はii/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)
于 2009-10-11T20:41:36.583 に答える
19

しばらく前に、 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であるという奇妙なケースが発生する可能性があります。そのため、max1未満のものを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,:);

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

于 2009-10-11T17:25:36.120 に答える
2

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

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

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

output = imresize(input,2,'nearest');
于 2009-10-11T15:11:13.040 に答える
0

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

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

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

于 2009-10-11T15:01:04.387 に答える