Page 1 of 1

exposure compensation?

Posted: 2008-06-06T01:36:05-07:00
by cedricb
Hi,

I've got two images which are 4 stop apart (in 16bits linear TIFF from dcraw). I would like to apply a negative exposure compensation (-4) to the over-exposed image (+4EV). The aim is to create a layer mask to reduce noise from the normal exposed shot.

The mask will be composed of:
- a negate version of the over-exposed image
- a corrected over exposed image from the over-exposed image (that's what I'm trying to do)
- merge the negate image to the alpha channel of the corrected over-exposed image

Finally I'll overlay the mask to the normal image.

So far I've got these:

step 1 --> convert overexposed.tiff -negate negate.tiff
step 2 --> ???
step 3 --> composite -compose CopyOpacity negate.tiff corrected_overexposed.tiff mask.tiff
step 4 --> composite normal.tiff mask.tiff merge.tiff (need to test this, don't know if I need to use -blend)

Can I achieve this with ImageMagick? and do I need to enable HDRI?


Regards,
Ced.

Re: exposure compensation?

Posted: 2008-06-06T12:02:26-07:00
by fmw42
you need to explain how you want to correct the overexposed image for step 2, that is what is the formula or processing that you need to do

Re: exposure compensation?

Posted: 2008-06-07T09:30:11-07:00
by cedricb
I don't know the maths but I would like to reproduce the following tutorial: http://jtrujillo.net/qpix/

The image A is my normal exposed one, the image C is my over-exposed one and the image B is the one I'm trying to acheive from C.

Re: exposure compensation?

Posted: 2008-06-08T12:18:01-07:00
by dognose
you can just use -average to combine the two pics (or more)

for the mind blowing hdr style pics, you'd need to use tone mapping, which I don't think there is any support for in IM.

It does support hdr format if you enable hdr while compiling.

Re: exposure compensation?

Posted: 2008-06-09T00:02:54-07:00
by cedricb

Re: exposure compensation?

Posted: 2008-06-17T08:48:49-07:00
by cedricb
up! :o

Re: exposure compensation?

Posted: 2008-06-17T11:48:06-07:00
by fmw42
Sorry, I don't have any answer for this

Re: exposure compensation?

Posted: 2008-08-18T02:07:57-07:00
by cedricb
I've finally found the logarithmic formula... so I've tried to multiply the linear data with 2^-4

convert test.tiff -fx 'u*2^-4' corrected.tiff

I takes ages (with a core2duo) with an images of 3474x2314, is it possible to optimize this?

Re: exposure compensation?

Posted: 2008-08-18T11:19:45-07:00
by fmw42
If this is really what you need, then you are simply multiplying the image by 2^-4 = 1/2^4 = 1/16 = 0.0625. Multiplying the image by such a small number will make your image very dark. But if that is what you want to do, then use -evaluate multiply 0.0625

See -evaluate at http://www.imagemagick.org/script/comma ... p#evaluate

Re: exposure compensation?

Posted: 2008-08-18T17:46:12-07:00
by anthony
From what I can see the key is the creation of the image mask, so that you can then use it with a three image composite blend.

That is...

Code: Select all

   convert   image1.png  image2.png  blend_mask.png \
           -compose Src -composite  result.png
The tricky part is generating the right type of mask which is black where you want the first image, white where you want the second image, and the appropriate shade of gray when you want a blended weighted average between the two images.

One image is the normal exposure, while the other the corrected over exposure image. Which image is which does not matter, as if the images are swapped, you just use a negated mask instead (swap black and white when you swap images).

In many ways this is similar to the 'Double Exposure' technique I example in IM Examples, Photo Handling, but for noise reduction improve the Dynamic range of the resulting image so both the detail in both the bright and dark areas are much more visible.

The article however is not really very clear about how to go about generating that mask, as it is expressed in photoshop terms, such as
the overexposed image with all the highlights clipped .. copy to clippboard
and later
And this the result after some additional processing to boost the shadows
which is about as clear as MUD.

Re: exposure compensation?

Posted: 2008-08-19T02:03:08-07:00
by cedricb
Thanks a lot, it's much faster! from 6min to 2s... :-)

Here is an example with hdr1.tiff the normal exposed image (full of noise in the shadow) and hdr3.tiff the +4EV over-exposed

Code: Select all

convert hdr3.tiff -negate negate.tiff
ec=$(echo 'e(l(2)*-3.93)' | bc -l)
convert hdr3.tiff -evaluate multiply $ec corrected.tiff
composite -compose CopyOpacity negate.tiff corrected.tiff mask.tiff
composite -blend 90 mask.tiff hdr1.tiff merge.tiff

convert -gamma 2.2 merge.tiff -channel ALL -normalize -quality 100 result.jpg
My next task is to calculate the real exposure difference between 2 source images. For my example the second image has +4EV but in reality is +3.93EV. By doing this I'll have a smooth blending mask.

The tricky part is to find the correct ratio for the blending...

Re: exposure compensation?

Posted: 2008-08-19T21:59:41-07:00
by anthony
Do you have two images I can use as an example of doing this? I would like to try to explain how to do this in IM examples Photo Handling.

Re: exposure compensation?

Posted: 2008-08-20T01:17:38-07:00
by cedricb
This technique is from this tutorial --> http://www.guillermoluijk.com/tutorial/ ... /index.htm

That's the images I've used to be able to compare from the tutorial
http://www.guillermoluijk.com/download/hdr1.cr2
http://www.guillermoluijk.com/download/hdr3.cr2

Here is the dcraw command lines to get a linear 16bits TIFF with the camera WB:

Code: Select all

dcraw -v -w -W -o 0 -q 3 -4 -T hdr1.cr2
dcraw -v -w -W -o 0 -q 3 -4 -T hdr3.cr2
Before doing a chapter in your documentation, I need to figure out how to calculate the exact exposure and if it's possible to get the optimum blending ratio.

For the exposure difference, can I do this with the IM command line tools or do I need to use the API?

Re: exposure compensation?

Posted: 2008-08-20T22:17:59-07:00
by anthony
cedricb wrote:For the exposure difference, can I do this with the IM command line tools or do I need to use the API?
I think you will need to use some mix of Im with some API calculations.

The tricky part is finding some area of the image that is common to both images BUT which has not been clipped by the over exposure. From this the difference should be calculated and thus determining the adjustment needed using whatever function you use to do the exposure adjustment.

Re: exposure compensation?

Posted: 2008-08-21T00:24:41-07:00
by cedricb
First draft implementation of the exposure calculation between 2 images. I don't know if there is a simple solution or more elegant solution to do this, for the time been it works...

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <wand/MagickWand.h>

int main(int argc,char **argv) {
  MagickBooleanType status;
  MagickPixelPacket pixel1, pixel2;
  MagickWand *image1, *image2;
  PixelIterator *iterator1, *iterator2;
  PixelWand **pixels1, **pixels2;

  long y;  
  register long x;
  unsigned long width;

  double min = 65536 / pow(2, 6);
  double max = 65536 * 0.9;
  double sum1 = 0, sum2 = 0;

  if (argc != 3) {
      fprintf(stdout, "Usage: %s normal-image over-exposed-image\n", argv[0]);
      exit(0);
  }

  MagickWandGenesis();
  image1 = NewMagickWand();
  status = MagickReadImage(image1, argv[1]);
  if (status == MagickFalse) {
    return -1;
  }
  image2 = NewMagickWand();
  status = MagickReadImage(image2, argv[2]);
  if (status == MagickFalse) {
    return -1;
  }

  iterator1 = NewPixelIterator(image1);
  iterator2 = NewPixelIterator(image2);
  if ((iterator1 == (PixelIterator *) NULL) || (iterator2 == (PixelIterator *) NULL)) {
    return -1;
  }
  for (y=0; y < (long) MagickGetImageHeight(image1); y++) {
    pixels1 = PixelGetNextIteratorRow(iterator1, &width);
    pixels2 = PixelGetNextIteratorRow(iterator2, &width);
    if ((pixels1 == (PixelWand **) NULL) || (pixels2 == (PixelWand **) NULL)) {
      break;
    }
    for (x=0; x < (long) width; x++) {
      PixelGetMagickColor(pixels1[x], &pixel1);
      PixelGetMagickColor(pixels2[x], &pixel2);
      if ((pixel1.red >= min) && (pixel1.red <= max) && (pixel2.red >= min) && (pixel2.red <= max)) {
         sum1 += pixel1.red;
         sum2 += pixel2.red;
      }
      if ((pixel1.green >= min) && (pixel1.green <= max) && (pixel2.green >= min) && (pixel2.green <= max)) {
         sum1 += pixel1.green;
         sum2 += pixel2.green;
      }
      if ((pixel1.blue >= min) && (pixel1.blue <= max) && (pixel2.blue >= min) && (pixel2.blue <= max)) {
         sum1 += pixel1.blue;
         sum2 += pixel2.blue;
      }
    }
  }
  if (y < (long) MagickGetImageHeight(image1)) {
    return -1;
  }
  iterator1 = DestroyPixelIterator(iterator1);
  image1 = DestroyMagickWand(image1);
  iterator2 = DestroyPixelIterator(iterator2);
  image2 = DestroyMagickWand(image2);
  MagickWandTerminus();

  printf("%.100g\n", sum1/sum2);
  return(0);
}

Code: Select all

gcc `Magick-config --cflags --cppflags` -o exposure exposure.c `Magick-config --ldflags --libs`