2
$\begingroup$

I have a set of microscope images that were produced in a 5x5 grid (actually 9x9 but for the purpose of this example I'm keeping it small). However, they were not taken in the same order that they appear spatially, so I want to rearrange their placement so that they appear in the right order.

The original image order looks like this, representing how the images are supposed to be laid out spatially, and which order the camera took these pics:

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

Consequently, the current list of images looks like {img1, img2, img3, img4, img5, img6 ... img25}, but I want to create a an indexing list index = {25, 24, 23, 22, 21, 16, 17, 18, 19, 20, 1, 2, 3, 4, 5, 10, 9, 8, 7, 6, 11, 12, 13, 14, 15}. If I can create this index, it should be fairly easy to simply reorder the images in this way. To clarify: the current form of the data is a list of image files, and I want to create a new indexing list of numbers that I can use to re-index this list of images.

So, my question is: given an n*n grid, how do I create an index list that follows the above snaking pattern? So far, my code looks like this:

ReorderImages[stack_] := Block[{length, edge, startRow, firstBatch, secondBatch, indices, output},
  length = Length[stack]; (*Length will always be a square of an oddnumber*)
  edge = Sqrt[length]; (*Edge length*)
  startRow = Ceiling[edge/2];
  firstBatch = edge * startRow; (*The first "batch" of images taken. Here, 1-15. Not sure what to do about 16-25*)

  indices = {(*Stuck on how to create this part*)};

  output = stack[[indices]]
  ]

Thanks.

$\endgroup$
7
  • $\begingroup$ Welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Take the tour! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! $\endgroup$
    – Michael E2
    Aug 11, 2016 at 16:35
  • $\begingroup$ Do you want to combine your 25 images in a single big image? $\endgroup$
    – BlacKow
    Aug 11, 2016 at 16:42
  • $\begingroup$ Yes. The idea is that after they're all in the right order, I can stitch them together as a composite instead of as a list/stack. $\endgroup$
    – Ed Doe
    Aug 11, 2016 at 16:43
  • 1
    $\begingroup$ Have you seen ImageAssemble[] and ImageCollage[]? $\endgroup$ Aug 11, 2016 at 17:13
  • $\begingroup$ For the time it takes to type out a question or answer -- even for me to type this comment -- I could have probably typed the 81 indices in the right order and used an approach like Bob Hanlon's deleted answer. $\endgroup$
    – Michael E2
    Aug 11, 2016 at 19:15

2 Answers 2

3
$\begingroup$

Not as clever as David Stork's solution, but works for for larger grid sizes:

Clear[reorder]
reorder[stack_] := Module[{length, edge, grid, startRow, reverseEven},
  length = 
   Length[stack];(*Length will always be a square of an odd number*)
  edge = Sqrt[length];

  (* partition the flat list into 2d grid *)
  grid = Partition[stack, edge];

  (* move bottom rows to the top *)
  startRow = Ceiling[edge/2];
  grid = Join[Reverse[grid[[startRow + 1 ;;]]], grid[[;; startRow]]];

  (* reverse even rows below the split, odd rows above *)
  reverseEven[row_, {index_}] := 
   If[Xor[OddQ[index], index >= startRow], Reverse[row], row];
  grid = MapIndexed[reverseEven, grid];

  grid]

So reorder[Range[5^2]] // Grid returns:

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

Or, in a plot:

rng = Range[9^2];
order = reorder[rng];
ListLinePlot[Reverse[Position[order, #][[1]]] & /@ rng, Mesh -> All, 
  AspectRatio -> 1] /. Line -> Arrow

enter image description here

$\endgroup$
1
  • $\begingroup$ Excellent! However, your code as it currently stands flips the rows wrong if the edge length is 1 less than a multiple of 4. A quick change to the definition of reverseEven fixes this: reverseEven[row_, {index_}] := If[Mod[edge + 1, 4] == 0, If[Xor[EvenQ[index], index >= startRow], Reverse[row], row], If[Xor[OddQ[index], index >= startRow], Reverse[row], row]]; $\endgroup$
    – Ed Doe
    Aug 11, 2016 at 18:49
2
$\begingroup$

Too clever by half:

Map[img, MapAt[Reverse, Permute[Partition[Range[25], 5],
   Cycles[{{1, 3, 5}, {2, 4}}]] , {{1}, {4}}] , {2}] //MatrixForm

The approach can be extended to arbitrary (odd) $n$:

n = 5; (* n must be odd *)

Map[img, MapAt[Reverse, 
   Permute[Partition[Range[n^2], n], 
    Cycles[{Range[1, n, 2], 
      Range[2, n, 2]}]], {{1}, {4}}], {2}] // MatrixForm

...but I haven't the time to work out a general formula for the reversing of rows. Perhaps Ed Doe has the time...

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.