views:

117

answers:

2

EDIT:-

a4 = 10*magic(4);
a5 = magic(5);
a4
a5

diag4 = sub2ind([4,4], 1:3,1:3);
diag5 = sub2ind([5,5], 1:3,1:3);
a5(diag5) = a4(diag4)    #Display changed contents
diag4   %#  Display diagonal of magic4        
diag5  %# Display diagonal of magic5

 a4(diag4)=a5(diag5) %# recovering the original

The output is

a4 =                     %# Display of original a4 magic square

   160    20    30   130
    50   110   100    80
    90    70    60   120
    40   140   150    10

a5 = %#Display of original magic square

17    24     1     8    15
23     5     7    14    16
 4     6    13    20    22
10    12    19    21     3
11    18    25     2     9


diag4 =

     1     6    11


diag5 =

     1     7    13


a5 =

   160    24     1     8    15
    23   110     7    14    16
     4     6    60    20    22
    10    12    19    21     3
    11    18    25     2     9




a4 =

   160    20    30   130
    50   110   100    80
    90    70    60   120
    40   140   150    10

Question is I cannot figure out the logic behind the manner in which diag4 and diag5 have been generated.

A: 

one way to access the diagonal elements of a matrix (get or assign) is to use sub2ind to find the entries

>> a = magic(4);
>> ind = sub2ind([4,4], 1:3,1:3);
>> a(ind) = rand(1,3)

a =

    0.6551    2.0000    3.0000   13.0000
    5.0000    0.1626   10.0000    8.0000
    9.0000    7.0000    0.1190   12.0000
    4.0000   14.0000   15.0000    1.0000

Edit: Adding second example

% replace the first 3 items in the diagonal of a5 by 
% the first 3 items in the diagonal of a4
>> a4 = 10*magic(4);
>> a5 = magic(5);
>> diag4 = sub2ind([4,4], 1:3,1:3);
>> diag5 = sub2ind([5,5], 1:3,1:3);
>> a5(diag5) = a4(diag4)

a5 =

   160    24     1     8    15
    23   110     7    14    16
     4     6    60    20    22
    10    12    19    21     3
    11    18    25     2     9
second
@second. Ok, so instead of using rand to populate the array a, can we use a 3D matrix which in my case is an image B?If so then what will be the entries in the brackets of the image.Also, i really need to use sort function so as make the whole process reversible/invertible. There is another command eye,with which diagonals can be retrieved. Do correct me if i am wrong. Thank you.
sumona
eye creates an identity matrix. you can use sub2ind twice, once to extract the diagonal entries, if you want run some operation on them, and then to assign to the diagonal of the output
second
@second. The code works fine for vector with different size. But in the case of matrices with similar size, how would the the variable diag4 and diag5 know whose diagonal elements they contain.say size(a4)=size(a5)=5 5 . Then diag4=diag5!! which should not be so. Please clarify.
sumona
@second,regarding the way diagonals are fetched, i have an important question. If you would kindly go through this link http://stackoverflow.com/questions/3689840/how-to-find-correlation-of-an-image which has been answered. In the answer, it is mentioned a way to fetch adjacent diagonal pixels. So, is this another way to fetch the pixels?
sumona
diag is just a list of the indecies which correspond to the diagonal. this depends on size but not on the matrix entries. to extract the entries we index into the actual matrix: diag = indecies, a5(diag) = entries
second
@second,actually this is the "Objective " of the above code >>>to extract the entries of the pixels in image/matrix A1 along the diagonal which will be fed into the matrix B1 along its diagonal as the diagonal elements of B1. So if you could kindly modify your answer accordingly so as to extract pixels along the diagonal. Thank you once again.
sumona
@second,I have executed your code to get an output which is put up in the question as an EDIT version of the original question. I am unable to follow however what exactly is going on and diag4 and diag5 are being substituted in the main matrix. Kindly explain. Thank you for your time and effort.
sumona
+1  A: 

I'm not totally clear about your goal, still here's one way to extract the diagonals of an RGB image (diagonal of 2D matrices for each color channel):

A = rand(32,32,3);   %# it can be any 3D matrix (and not necessarily square)
[r c d] = size(A);
diagIDX = bsxfun(@plus, 1:r+1:r*c, (0:d-1)'.*r*c);
A( diagIDX(:) )

diagIDX will have three rows, each contain the (linear) indices of the diagonal elements (one for each slice). From there you can adapt it to your code...


The idea behind the above code is simple: take a 2D matrix, the diagonal elements can be accessed using:

A = rand(5,4);
[r c] = size(A);
A( 1:r+1:r*c )

then in the 3D case, I add an additional offset to reach the other slices in the same manner.

Amro
@Amro,there is an error due to this >> Undefined command/function 'bsxfun'. Also, on fetching the pixels along A( diagIDX(:) ) how do i replace another image's, say B, diagonal elements with the output of A( diagIDX(:) ) and display B in the form of an image of size A. This is the main concern and the question re formulated.Kindly address this issue.
sumona
@sumona: BSXFUN function was introduced in MATLAB R2007a. If you have an older version, you can still do the same with: `diag2D = 1:r+1:r*c; diag3D = repmat(diag2D, [d 1]) + repmat((0:d-1)' .* r*c, [1 length(diag2D)]);`. Now if I understand correctly, you have two images A and B of same size, then you can replace diagonals of B with diagonals of A using: `B(diagIDX(:)) = A(diagIDX(:))`. If the images are not of the same size, you would have to make sure to limit the indices to that of the smaller matrix to avoid `Index exceeds matrix dimensions` errors...
Amro
@Amro,thank you for the reply. Could you also explain from the output posted in the question how a4= 1 6 11 ?Since these are the first three diagonal elements and 1 6 11 are not listed as the first 3 elements.Thank you.
sumona
@sumona: in your example, `diag4` is a vector of indices NOT the values themselves (MATLAB emply a column-major order), to access the values at those indices, use `a4(diag4)`
Amro
@Amro,oh i got it.Thanx
sumona