4

I am using the answer of bill s in Greater operator should give greater element.

Here he showed the example:

lst1 = {{1, 2}, {3, 4}}; lst2 = {{5, 1}, {7, 2}};

max[list1_, list2_] := Module[{out}, Unprotect[Max]; SetAttributes[Max, Listable];
  out = Max[list1, list2]; ClearAttributes[Max, Listable]; out];

max[lst1, lst2]

{{5, 2}, {7, 4}}

Now I would like to apply it to two images:

image 1:

enter image description here

image 2:

enter image description here

I though the code below would show the superposed image with max intensity at each pixel.

imageData1=ImageData[image1];
imageData2=ImageData[image2];

maxImage=Image[max[imageData1,imageData2]]

The result is a message:

Image::imgarray: The specified argument 1.` should be an array of rank 2 or 3 with machine-sized numbers. >>

What do I wrong?

mrz
  • 11,686
  • 2
  • 25
  • 81

2 Answers2

8

Alternative solutions: You could use ImageApply on images:

ImageApply[Max, {i1, i2}]; // RepeatedTiming

{0.0239, Null}

Or MapThread on lists:

Image[MapThread[Max, ImageData /@ {i1, i2}, 2]]; // RepeatedTiming

{0.0231, Null}

And, somewhat surprisingly this uses 2 multiplications and 3 additions per pixel:

 (
   {d1, d2} = ImageData /@ {i1, i2};
   comp = UnitStep[d1 - d2];
   Image[comp*d1 + (1 - comp)*d2]
   ); // RepeatedTiming

{0.00069, Null}

and is still > 30 times faster.

Even more surprisingly (to me):

(
  comp = Binarize[ImageSubtract[i1, i2], 0];
  ImageAdd[ImageMultiply[comp, i1], 
    ImageMultiply[ColorNegate@comp, i2]]
 ); // RepeatedTiming

{0.0017, Null}

Is slower than the double precision arithmetic version above. Apparently, ImageAdd and friends aren't very efficient.

Niki Estner
  • 36,101
  • 3
  • 92
  • 152
  • I vote for your {d1, d2} solution. I tested a superposition of sequentiell gray scale images (286 png 8bit images, each 347*347 pixels). The code {d1, d2} = ... is in total about 4 times faster than using ImageApply[Max, {img1, img2}]. See https://imgur.com/MhJApXv and https://imgur.com/9Thol7v. – mrz Jul 05 '16 at 08:40
6

It's simpler than that, since you can use the built-in image processing function ImageApply:

img1 = Import["https://i.stack.imgur.com/bBsDH.png"];
img2 = Import["https://i.stack.imgur.com/O9Vm6.png"];
ImageApply[Max, {img1, img2}]

enter image description here

bill s
  • 68,936
  • 4
  • 101
  • 191
  • Upvote.I have to say the ImageApply is low efficiency function.Maybe ImageAdjust[ImageAdd[img1, img2]] is enough – yode Jul 04 '16 at 17:17
  • 1
    @yode -- it may not be particularly efficient to run, but it is very efficient to write. And it is also very flexible since you can use any function (with the right number of inputs and outputs), not just Max. – bill s Jul 04 '16 at 17:20
  • Thank you for your help. Please see my comment below nikies answer. Do you know why your code in http://mathematica.stackexchange.com/questions/97918/greater-operator-should-give-greater-element is not applicable? – mrz Jul 05 '16 at 08:43