Calculate exposure difference between two shots

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
luigi

Calculate exposure difference between two shots

Post by luigi »

Hi All!

I'm trying to port a ver cool set of tools/script by Cedric Bompart to Windows, you can find them here:
http://cbompart.wordpress.com/

What I need is a tool that calculates the exposure difference between two shots. Cedric used a "C" program but I have no C compiler for Windows, I wonder if I can use Identify in some way to compute the same?

In short words can I do what this "C" program does with identify or some commandline tool ?

Thanks!!

Here is the C program if you want to take a look:

Code: Select all

01   #include <stdio.h>
02	#include <stdlib.h>
03	#include <math.h>
04	#include <wand/MagickWand.h>
05	 
06	int main(int argc,char **argv) {
07	  MagickBooleanType status;
08	  MagickPixelPacket pixel1, pixel2;
09	  MagickWand *image1, *image2;
10	  PixelIterator *iterator1, *iterator2;
11	  PixelWand **pixels1, **pixels2;
12	 
13	  long y;
14	  register long x;
15	  unsigned long width;
16	 
17	  double min = 65536 / pow(2, 6);
18	  double max = 65536 * 0.9;
19	  double sum1 = 0, sum2 = 0;
20	 
21	  if (argc != 3) {
22	      fprintf(stdout, "Usage: %s normal-image over-exposed-image\n", argv[0]);
23	      exit(0);
24	  }
25	 
26	  MagickWandGenesis();
27	  image1 = NewMagickWand();
28	  status = MagickReadImage(image1, argv[1]);
29	  if (status == MagickFalse) {
30	    return -1;
31	  }
32	  image2 = NewMagickWand();
33	  status = MagickReadImage(image2, argv[2]);
34	  if (status == MagickFalse) {
35	    return -1;
36	  }
37	 
38	  iterator1 = NewPixelIterator(image1);
39	  iterator2 = NewPixelIterator(image2);
40	  if ((iterator1 == (PixelIterator *) NULL) || (iterator2 == (PixelIterator *) NULL)) {
41	    return -1;
42	  }
43	  for (y=0; y < (long) MagickGetImageHeight(image1); y++) {
44	    pixels1 = PixelGetNextIteratorRow(iterator1, &width);
45	    pixels2 = PixelGetNextIteratorRow(iterator2, &width);
46	    if ((pixels1 == (PixelWand **) NULL) || (pixels2 == (PixelWand **) NULL)) {
47	      break;
48	    }
49	    for (x=0; x < (long) width; x++) {
50	      PixelGetMagickColor(pixels1[x], &pixel1);
51	      PixelGetMagickColor(pixels2[x], &pixel2);
52	      if ((pixel1.red >= min) && (pixel1.red <= max) && (pixel2.red >= min) && (pixel2.red <= max)) {
53	         sum1 += pixel1.red;
54	         sum2 += pixel2.red;
55	      }
56	      if ((pixel1.green >= min) && (pixel1.green <= max) && (pixel2.green >= min) && (pixel2.green <= max)) {
57	         sum1 += pixel1.green;
58	         sum2 += pixel2.green;
59	      }
60	      if ((pixel1.blue >= min) && (pixel1.blue <= max) && (pixel2.blue >= min) && (pixel2.blue <= max)) {
61	         sum1 += pixel1.blue;
62	         sum2 += pixel2.blue;
63	      }
64	    }
65	  }
66	  if (y < (long) MagickGetImageHeight(image1)) {
67	 
68	    return -1;
69	  }
70	  iterator1 = DestroyPixelIterator(iterator1);
71	  image1 = DestroyMagickWand(image1);
72	  iterator2 = DestroyPixelIterator(iterator2);
73	  image2 = DestroyMagickWand(image2);
74	  MagickWandTerminus();
75	 
76	  printf("%.100g\n", sum1/sum2);
77	  return(0);
78	}
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Calculate exposure difference between two shots

Post by fmw42 »

I don't read C code very well, but it looks to me like it is just the ratio of the over all mean value of each image over all 3 channels (apart from some odd min (1024) and max (58982.4) values, which requires 16-bit image values)

Image

Image


mean1=`convert zelda3.png -format "%[mean]" info:`
mean2=`convert zelda3_level_25x75.png -format "%[mean]" info:`
ratio=`convert xc: -format "%[fx:$mean1/$mean2]" info:`
echo "exposure ratio = $ratio"
exposure ratio = 1.05875


Implementing his formula with the min and max values could be done by masking the images for these min and max values (after converting to 16-bits), multiplying the masks, then multiplying the composite mask by each image, then computing the mean of the non-masked areas. see http://www.fmwconcepts.com/imagemagick/ ... shape_mean
luigi

Re: Calculate exposure difference between two shots

Post by luigi »

Thanks, a lot for your info.

I think masking those values is to eliminate blownup and underexposed pixels from the picture. In other words averaging only the pixels that do contain information. Is there an easy way to do that ?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Calculate exposure difference between two shots

Post by fmw42 »

use a combination of -black-threshold and -white-threshold to create the mask (see http://www.fmwconcepts.com/imagemagick/ ... olor_slice or my script, slice, see link below).

note that you must be using Q16 IM compilation so that you can use the 16-bit min and max values he specified.
luigi

Re: Calculate exposure difference between two shots

Post by luigi »

Thanks a lot sorry for asking but can you help me with the commands I'd need to use, I'm a total neewb with IM and I think I need some help to get started.
Can you please write the commands to get the mean of the image masking the min and max values?

Thanks a lot (I'm ashamed)
fmw42 wrote:use a combination of -black-threshold and -white-threshold to create the mask (see http://www.fmwconcepts.com/imagemagick/ ... olor_slice or my script, slice, see link below).

note that you must be using Q16 IM compilation so that you can use the 16-bit min and max values he specified.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Calculate exposure difference between two shots

Post by fmw42 »

give me a day or two to get to it. it is not hard but I have other commitments. I will work on it as I can. Do you want to wait for me to write it as a script or just want the command lines to do it?

Also please explain what you will do with the exposure difference, once it can be computed. Perhaps there are other ways to already achieve your objective.

You might look over my existing scripts and see if one of them does what you need. Such as bcmatch, histmatch, redist, autolevel, etc
luigi

Re: Calculate exposure difference between two shots

Post by luigi »

A day or two? Thanks!!!!
Commandline is preferred as I have no compiler on my PC, I just installed the ImageMagick Windows Installation by default and it's the only thing I have.

The exposure difference will be used to create a batch script that creates a noise free image from a series of exposures. It's an idea from Cedric Bompart that I'm migrating to windows. You can read and get his Linux scripts here:
http://cbompart.wordpress.com/2009/12/0 ... agemagick/

As you can see he created a C program "exposure" that was the one I pasted in my first post to calculate the exposure. This is the only missing link I have to migrate everything to Windows.

Once again thanks a lot for your kind help, if I can help you in anything you need photography related please let me know.

Cheers
Luis
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Calculate exposure difference between two shots

Post by fmw42 »

please note that I am on a Mac/Unix computer and there are difference between the Unix and Windows syntax for IM. My code will be unix. I know little about Windows. So you will need to convert it to Windows format. See the extensive notes about the differences at http://www.imagemagick.org/Usage/windows/
luigi

Re: Calculate exposure difference between two shots

Post by luigi »

Sure, thanks for the link as long as It's commandline and I don't have to compile anything it will be fine!
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Calculate exposure difference between two shots

Post by fmw42 »

Here is my best cut at it for now. It creates a mask from the first image, a mask from the second image (based upon the min and max values), then multiplies the two masks together to get the composite mask (on a channel by channel basis). Then multiplies the mask by both images. Normally to get the mean of a masked image, one has to divide the mean of the masked image by the mean of the mask. But as you are forming a ratio, dividing both numerator and denominator by the same mask mean cancels out. So you don't need to compute the mean of the mask and do the divisions. Just find the ratio of the means of the two masked images. As this is not a script, I cannot automatically delete the two tmp files. So, you will have to manually delete the two tmp files, tmp1.png and tmp2.png.

infile1="zelda3.png"
infile2="zelda3_level_25x75.png"
min=`convert xc: -format "%[fx:65536/(2^6)]" info:`
max=`convert xc: -format "%[fx:65536*0.9]" info:`

convert $infile1 $infile2 \
\( -clone 0 -separate \
-black-threshold $min -white-threshold $max \
-fill black -opaque white -fill white +opaque black \
-combine \) \
\( -clone 1 -separate \
-black-threshold $min -white-threshold $max \
-fill black -opaque white -fill white +opaque black \
-combine \) \
\( -clone 2 -clone 3 -compose multiply -composite \) \
\( -clone 0 -clone 4 -compose multiply -composite -write tmp1.png \) \
\( -clone 1 -clone 4 -compose multiply -composite -write tmp2.png \) \
null:

mean1=`convert tmp1.png -format "%[mean]" info:`
mean2=`convert tmp2.png -format "%[mean]" info:`
ratio=`convert xc: -format "%[fx:$mean1/$mean2]" info:`
echo "mean1=$mean1; mean2=$mean2; ratio=$ratio"
mean1=32616.2; mean2=31435.9; ratio=1.03755
Last edited by fmw42 on 2009-12-03T10:11:52-07:00, edited 1 time in total.
cedricb
Posts: 28
Joined: 2008-06-06T01:33:22-07:00

Re: Calculate exposure difference between two shots

Post by cedricb »

Hi,

Thanks a lot for the plug and play script, so I can remove my C program from my bash script... ;-) I'll test your script tonight.

The min value is supposed to skip the 7th or lower f-stop values which is really noisy. And the max value is supposed to skip the values higher than 90% due to non-linearity of the camera sensor.
These 2 values are just guessing so I don't know if there is a way to detect an optimum threshold ?


Regards,
Ced.
luigi

Re: Calculate exposure difference between two shots

Post by luigi »

Hi Cedric!

If you test the script please let me know if the values are the same as your exposure program, then I can migrate everything to windows and give it to you as a zip file so you can release the Linux and Windows version of ZeroNoise & Tonemapping. I think it can be a great package.

fm242: I'd like to credit you for your work in the package doc if you are ok with this give me your name.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Calculate exposure difference between two shots

Post by fmw42 »

see my web page below

let me know how the comparison works out.
cedricb
Posts: 28
Joined: 2008-06-06T01:33:22-07:00

Re: Calculate exposure difference between two shots

Post by cedricb »

Hi,

Yes the comparison is fine, just the scale due to the value returned from the identify mean. I need to play around with your "huge" command to understand everything...

Regards,
Ced.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Calculate exposure difference between two shots

Post by fmw42 »

The mean is just the sum/number-of-pixels. Another difference is that I did not divide the mean of the masked image by the mean of the mask as the mean of the mask would cancel out in both the numerator sum and the denominator sum.

The code produces a mask for the first image in the first paren by using -black-threshold to make everything below the min black, then using -white-threshold to make everything that is above the max white, then it changes white to black and then changes everything not black to white. Thus everything below the min and above the max is black and everything else is white. The same is done in the second paren to the second image. Then the two masks are multiplied in the third paren. Then the mask is multiplied by each image in the 4th and 5th paren and the masked images are written out and the command is ended by a null: to get rid of all the previous images. Then the means of the two masked images are computed and finally the ratio of the two means is produced.

The means include the black pixels, but as I have said before it does not matter that I did not divide by the means of the masks to compensate as that division would cancel out when the two means were divided. So the means (even multiplied by the number of masked pixels) would not be the same as his sums. But the ratios should still be the same.
Post Reply