0
votes

I'm trying to implement the nearest neighbor algorithm for scaling pictures on Matlab. I'm trying to implement it without using any loops - as, from what I gather, using matrixes greatly improves performance. I'm really having a lot of trouble finding how to do so. I think this should be the correct procedure:

  1. Find the width and height ratio for the scaled picture
  2. Compute a matrix of dimension (width*scale, height*scale) containing the nearest neighbor indices for each cell
  3. Apply this matrix to the starting picture('s matrix) to get the scaled picture

I'm getting really confused on how matrix and their operations work in Matlab.

This is how I would do it with loops:

x_ratio = width/(width*scale);
y_ratio = height/(height*scale);

for i=1:1:width
  for j=1:1:height
    x=i*x_ratio;
    y=j*y_ratio;
    out_image(i, j) = image(x, y);
  end
end

So far, I've managed to find that with matrices it should work too:

q =
  2×2 char array

    'ab'
    'cd'

>> q([1 1 3 3; 1 1 3 3; 2 2 4 4; 2 2 4 4])

ans =

  4×4 char array

    'aabb'
    'aabb'
    'ccdd'
    'ccdd'

My first question would be: why is it that [1 1 3 3; 1 1 3 3; 2 2 4 4; 2 2 4 4] produces the right result while it's represented as:

>> [1 1 3 3; 1 1 3 3; 2 2 4 4; 2 2 4 4]

ans =

     1     1     3     3
     1     1     3     3
     2     2     4     4
     2     2     4     4

I'd think that the correct matrix to pass to q would be:

>> [1 1 2 2; 1 1 2 2; 3 3 4 4; 3 3 4 4]

ans =

     1     1     2     2
     1     1     2     2
     3     3     4     4
     3     3     4     4

where, all the indices represent the correct index from the q matrix. But if I do, I get a matrix where c and b are inverted, and is wrong:

>> q([1 1 2 2; 1 1 2 2; 3 3 4 4; 3 3 4 4])

ans =

  4×4 char array

    'aacc'
    'aacc'
    'bbdd'
    'bbdd'

It just seems so... counterintuitive. Every semicolon in [1 1 3 3; 1 1 3 3; 2 2 4 4; 2 2 4 4] denotes a row, or a horizontal vector, from what I understand. So why when passed to another matrix it does seem to denote a vertical vector or a column? (If I'm not completely blind, this seems to be how it behaves in this case, considering the vector I pass to the smaller matrix as indexes of columns).

Secondly, how do I compute the [1 1 3 3; 1 1 3 3; 2 2 4 4; 2 2 4 4] matrix? Or more generally, I need to compute the matrix of the linear-indexes following the nearest neighbor rule, that is what I do in the first code block with the nested loops. This I think would be the crucial point, but I'm clueless as to how generalize the process to use with matrix. With the loops, I'd pass in each cell of the scaled matrix and calculate which corresponding cell of the original matrix goes where. So, for example, if I where to check scaled_matrix(i, j) I'd know that in that cell I'd have to put orig_matrix(i*x_ratio, j*y_ratio), and so on. My idea would be to computate scaled_matrix containing all the correct indexes, and then proceeding.

1
You can do the indexing using two vectors, one for all rows, one for all columns. You'd compute your row/column indices separately, say in Y and X, then do image(Y,X).Cris Luengo

1 Answers

1
votes

Answer to your first question is discussed in this question. Matlab stores its matrices in a column-major order. So for your character array q

q(1) = 'a'
q(2) = 'c'
q(3) = 'b'
q(4) = 'd'

That's why the correct matrix for scaling q to 4x4 is indeed [1 1 3 3; 1 1 3 3; 2 2 4 4; 2 2 4 4] and not the other matrix.

Your second question already has an answer in "Nearest-neighbor interpolation algorithm in MATLAB" post. The accepted answer in that post does not use any loops like you want.