I am currently trying to partition an image into several images with fixed size and no padding spanning the whole area of the original. Subsequently, I want to do an arbitrary operation on each image part and reassemble the image by overlaying the results of this operation (repeated entries could be replaced by a mean). This would mean that the image parts have variable offset and overlay with each other depending on the size of the original.

As far as I understand it the offset of ImagePartition is fixed and ImageAssemble can only work with parts that do not have any overlays.

It should be something like the following:

im = Import["ExampleData/spikey.tiff"]
(*this operation should give as many 100x100 images as are needed to cover all pixels of im possibly having considerable overlap*)
parts = ImagePartitionSpecial[im, {100, 100}]     
parts = DoArbitraryImageOperation@parts
(*this operation should assemble an image of the size im where repeated pixels should be replaced by a mean of them*)
result = ImageAssembleSpecial[parts] 

Has something like this been done before? Essentially my function only works on images of a fixed size so that I need to disassemble and reassemble the image I want to call it on. Note that setting a fixed offset of 1 would not be great as this will generate way too many parts.

Best, Max


1 Answer 1

im = Import["ExampleData/spikey.tiff"];

The following function makes intervals with size sz that covers Range[dim]

ints[dim_, sz_] := With[{mids = Range[(1 + sz)/2, ((dim - sz + 1) + dim)/2,
 (dim - sz)/Max[Quotient[dim, sz, 1], 1]]}, Floor[Outer[Plus, mids, {1 - sz, sz - 1}/2]]]

Combining such intervals in both image dimensions we get the subimage coordinates

subImageCoords[im_, w_, h_] := Outer[List, Sequence @@ Reverse[
                                MapThread[ints, {ImageDimensions[im], {w, h}}]], 1]

assem partitions with overlay using subimages with width w and height h. Then it applies some transformation trans to all subimages, and finally combines the subimages using ImageAdd (after dividing the overlay pixels by 2).

trans = Identity;

assem[im_, w_, h_] := Module[{data, makeTermRow, makeTermCol},

  makeTermRow = Function[{image, overlay, pad},
                         data = ImageData[image];
                         data[[;; overlay[[1]]]] /= 2;
                         data[[-overlay[[2]] ;;]] /= 2;
                         ImagePad[Image[data], {{0, 0}, pad}]];

  makeTermCol = Function[{image, overlay, pad},
                         data = ImageData[image];
                         data[[All, ;; overlay[[1]]]] /= 2;
                         data[[All, -overlay[[2]] ;;]] /= 2;
                         ImagePad[Image[data], {pad, {0, 0}}]];

  With[{pos = subImageCoords[im, w, h], imDim = ImageDimensions[im]},

    With[{newImages = Map[trans[ImageTake[im, Sequence @@ #]] &, pos, {2}],
          newDim = Dimensions[pos]},

      With[{newRows = ImageAdd /@ MapThread[makeTermCol, {newImages,
         ConstantArray[ArrayReshape[{0, w - Differences[pos[[1, All, 2]]], 0}, newDim[[{2, 3}]]], newDim[[1]]],
         ConstantArray[Transpose[Transpose[pos[[1, All, 2]]] {1, -1} - {1, -imDim[[1]]}], newDim[[1]]]}, 2]},

                      ImageAdd[MapThread[makeTermRow, {newRows,
         ArrayReshape[{0, h - Differences[pos[[All, 1, 1]]], 0}, newDim[[{1, 3}]]],
         Transpose[(Transpose[pos[[All, 1, 1]]] {1, -1} - {1, -imDim[[2]]})[[{-1, 1}]]]}]]]]]]

Now modify trans and call assem[im, 100, 100]


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.