0

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.

nash
  • 275
  • 1
  • 2
  • 12
  • 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 Nov 25 '17 at 02:05

1 Answers1

1

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.

  • Thanks, I didn't know about the column-major thing. But why is it that when I print `[1 1 3 3; 1 1 3 3; 2 2 4 4; 2 2 4 4]`, it is not printed as such that `[1 1 3 3]` is a column, but it is a row (like in the example I provided)? Also, looking at the variable in memory, I see that `[1 1 3 3]` is a row, and not a column. Does that mean that `[1 1 3 3]` is only considered a column when linear-indexing computations are involved? – nash Nov 24 '17 at 22:21
  • For the second question I've added more details to the OP. I'll inform myself better on the Kronecker Tensor Product - I don't know that one! – nash Nov 24 '17 at 22:23
  • You are correct. We need to be conscious of column-major memory layout only when dealing with linear-indexing. –  Nov 25 '17 at 04:26
  • Thanks, I finally understood how it works! A final question: If I pass a bigger matrix to a matrix (like in my example with `q` and `[1 1 3 3; 1 1 3 3; 2 2 4 4; 2 2 4 4]`), would the resulting matrix be the equivalent to the Kronecker Tensor Product between the two? – nash Nov 25 '17 at 09:11
  • You can see the examples on [this](https://www.mathworks.com/help/matlab/ref/kron.html) page about Kronecker-Delta product. It multiplies each element of a matrix with another matrix. Passing a bigger matrix, B, whose elements are within proper range of indices of smaller matrix A, as an index for matrix A returns a matrix of same size as B such that each element `B(i)` of B, is replaced by the corresponding element of `A( B(i) )`. This is more general than the Kronecker Tensor Product. –  Nov 25 '17 at 16:37