Thursday, October 23, 2008

Photometric measurements of a laptop monitor

This post completes the path from the journey from light intensity, or exposure, to pixels on the screen. In the last one I looked at how my Nikon D300 translates intensities in the scene being photographed into values in the RAW and JPEG files. The response of the RAW file is very linear, doubling the exposure (or equivalently intensity) doubles the value in the pixel in the RAW file. The response in the JPEG file is more complex; over a 4-stop range the value in the file increases as the log of the exposure. The final part of the story is how do these values in the file correspond to intensity on a computer monitor. As seen last week, RAW files from a digital camera are a good method of measuring intensity.. this is what is called photometry (at least in the field of astronomy).

The first interesting measurement that can be made with a D300 is the colour temperature (CT) of the monitor. One way to do this is to just take a bunch of JPEG shots of a white window on your monitor, with the white balance set to various colour temperatures. The image in which the Red, Green and Blue channels look the best matched is the one that had the correct colour temperature setting. You can see this on the D300 colour graphs, or offline using a program like photoshop. Some measured curves are below:

The photo with 4350K CT looks too blue, showing that the monitor is hotter than that. Similarly the 7140K shot is dominated by the red channel, indicating the CT is less than 7140K. The best match between all channels is at a colour temperature between 5500K and 5880K. Interestingly, according to Wikipedia the sRGB standard demands a CT of 6500K, so my monitor is evidently a little below the standard.

The second thing that can be measured is the intensity of the light generated by the monitor for a know intensity in an image file. The testcard I used, which was drawn with GIMP (similar to photoshop) is shown immediately below, and the photograph of how it appeared on my monitor is below it. To save space on the blog, the JPEG version of the photo is shown, but I used the RAW file for the photometry, since its response is linear.


The relationship between value in the testcard and intensity on the monitor is plotted below.

The response is somewhat linear over an approximately 5-stop range. However, even when taken on a dark evening (with the lights off!), the monitor does not go completely dark, which presumably means the LCD display is only "so good" at blocking the fluorescent backlight from shining through.

The characteristic curves of the camera and display can be put together to give an overall response, as shown below. The results are rather depressing, they make me feel like I should get a better display!

I would be interested to see how other displays respond.. would a really expensive display be more linear and go darker -- presumably a CRT could go completely dark. It's my impression that my old laptop had a better display than my newer one, I'll have to test it some time.

Saturday, October 11, 2008

D300 characteristic curve

I don't have very much new to report this week. My first week at my new job went well, the commute on the RER-B train is pretty easy, and I have a nice walk through Parc Montsouris to get to the local train station, and a 10 minute hike up the side of a hill to get to the lab at the other end, so it seems I will be staying fit even despite myself.

Over the last few weeks I've been reading The Negative, the second of Ansel Adam's series on photography. It's a really well written book, that describes how he went about bringing the vision he had for his photographs into reality. It details how he meters the scene, decides on exposure for the shot and what processing he will do to during development to enhance or contract the contrast. I was amazed at the laborious care he put into each photograph, far more than I put into mine... but then of course, his photos are far far superior than any of mine :-)

The other thing that is obvious from the book is that he had a complete understanding and mastery of all the technical aspects of photography. His book is full of scientific explanations of how film works, the nature of light, and how intensities in a scene relate to density on the film (and ultimately on paper), which he describes as the characteristic curve of the film. He devotes a large part of a chapter and a full appendix explaining these curves and how he and his assistant determined them for each combination of film type and development regime he used. It made me realize that there are large gaps in my knowledge of how my camera responds to light intensities, and that I really have no idea how well the monitor on my laptop renders intensities, except that I think it is not very good when I compare it by eye to other laptops. This post explores the first part of the problem, determining the relationship between exposure and the mean value in the RAW and JPEG output of my D300.

Actually it's pretty easy to determine the characteristic curve with a digital camera, you just have to take a bunch of photos of a uniformly illuminated screen, ranging from severely under-exposed to severely over-exposed, and determine the mean of the values in the image file. The D300 makes it easy to take both a RAW and JPEG files at once, which means you can work out the characteristic curve for both types of files with one set of shots. Alternatively if you have a different workflow, converting from RAW to JPEG using external software, you can use that also. To remove any headaches, it is probably best to set the white-balance to PREdefined and take a WB measurement off the screen before starting.

The plot shows the response of the RAW images (mean value in the image) over a 10-stop range. It is clear that the log of the mean signal in the RAW image increases linearly with the exposure in stops. A "zero" stop exposure, i.e. the exposure that the D300 metered as correct, and which should correspond to a middle gray exposure, creates a mean signal of approximately 300 in the RAW image. The sensor maxes out at 4096 (evidently a 14-bit sensor) about 4-stops over middle gray and reaches about 8 at 5-stops under middle gray.

The RAW data can be shown in a more useful form by plotting the y-axis as a base-2 logarithm relative to its "middle gray" value of 300, as above. In this form an increase in one unit on the y-axis corresponds to a doubling of the mean value in the RAW file, just as the exposure on the x-axis increases by a factor of two for each 1-stop increase. In this form it is clear that doubling (or halving) the exposure corresponds to a doubling (halving) of the mean value in the RAW file. The response is linear over an impressive 8-stop range, and possibly more.

The characteristic curve of the JPEGs produced by the camera is shown above. This curve has a 4-stop region around middle gray in which the response is roughly linear from an approximate value of 50 to 225. At lower values the response curves over, with the darker exposures being compressed into values below 50. At exposures 3-stops above middle gray, the curve saturates abruptly at a value of 255, unlike film which has a graceful rollover and some continued response even at high levels of over-exposures.

Another interesting thing that can easily be measured is the response of the camera to a middle gray exposure under different ISO settings. In the JPEG, the response is roughly constant, with the exposure being decreased as the ISO is increased, to maintain the middle gray level in the JPEG. The interesting thing (perhaps) is that it also remains roughly constant in the RAW file, as shown below, which means that the high ISO mode is implemented on the camera using a variable gain amplifier in the analog section of the CMOS sensor, rather than the camera digitally amplifying the value produced by the ADC.

Well that's it for now. Hopefully by next week I'll be able to measure the response of my laptop screen to fixed intensity images. That should be easy enough to do by photographing the screen of the laptop, since it's clear that the RAW file is very linear in its response to light.

Saturday, October 4, 2008

Debugging a serial (RS232) datastream with a digital storage oscilloscope

I'm finally in Paris, and loving it so far. It's a great city to walk around, there's so much to see. I spent most of my first day here out with my camera, with my home-made GPS switched on all day.. I got approximately 11 hours out of it before the battery died, and it wasn't even totally full to start with. Also the GPS seems to be very reliable now that I moved the wires from in front of its antenna.. it usually acquires its position a few 10s of seconds after it is switched on. After that it consistently re-acquires quickly as I come out of buildings and off of the Metro. I'm very happy with it now! The picture from Pont St Michel (above) was geotagged by my D300 with the following information:
  • Latitude: 40° 51.230' N
  • Longitude: 2° 20.683' E
  • Altitude: 40m
  • Time: 2008-10-04 13:25:50 UTC
If you build one of the interface circuits (either my design from the last post or one of the others from the web which use BJTs) you will probably want to test it before you connect it to your camera. An oscilloscope is the perfect tool for this. I tested my circuit initially using a 1970s vintage Tektronix 465 scope that I got on eBay for about $250 few years ago. An old analog scope like this does all you need to convince yourself that the voltage levels are right, i.e. between 0V and +5V and pegged at +5V when not transmitting. With an analog scope you can also check that the baud rate is right for the camera. At a baud rate of 4800 the duration of the smallest pulse should be 1/4800 = 0.208ms. You can also probably sell an old scope like the Tek'465 after you are finished with it for almost what you paid for it.

If you have access to a digital storage oscilloscope (DSO) or a USB oscilloscope, such as those made by Picoscope, you can also go one step further by decoding the serial datastream and making sure the information from the GPS is correct. If needs be you decode the RS232 stream directly from the GPS and the CMOS-level stream coming from the interface circuit. All the Picoscopes allow you to record the waveform and save it to your computer where the serial datastream can be decoded and examined. I used the Picoscope 3205 that my dad got me as a moving gift to save ~200,000 samples from the waveform generated by the interface circuit and wrote a small PERL program to convert it to ASCII. The figure below illustrates how first two characters in the serial data are encoded. The x-axis shows number of milliseconds since the time that the oscilloscope triggered at - it was set to trigger on the first transition from +5V to 0V. The y-axis shows the voltage at the output from the interface circuit.
The data is transmitted with an asynchronous serial start-stop format, in which the start of a character is indicated by the transmitter using a start bit, and the end of the character using one or more stop bits. In the figure above, the transmission is initially in the idle state, which has logic 1. The transmitter signals the start of a character with a logic 0 start bit, indicated by the first "s" in the figure. It then transmits the eight data bits, from least significant to most significant, indicated by 0-7. Finally it transmits two stop bits with logic 1, indicated by "S". The second character starts immediately, with the same sequence. The first two characters are:
  1. LSB-MSB: 00100100 = Decimal: 36 = ASCII: $
  2. LSB-MSB: 11100010 = Decimal: 71 = ASCII: G
which are the first two characters in the NMEA data messages. I wrote a small program in PERL which converts a set of voltage measurements into ASCII data. The data should be in a file with two columns, the first being a time measurement in milliseconds, the second a voltage. The script and two example files captured using my Picoscope are available on my website. For example, using the script on one of the example files (nmea2.txt) gives:

$GPGGA,152917.000,5317.5456,N,00614.3536,W,1,04,4.8,62.3,M,54.8,M,,0000*73
$GPGSA,A,3,16,06,23,31,,,,,,,,,6.3,4.8,4.1*3C
$GPGSV,3,1,11,16,56,290,36,24,46,077,20,21,45,147,13,31,45,203,33*77
$GPGSV,3,2,11,29,41,067,15,06,23,245,32,30,16,116,17,23,15,299,37*71
$GPGSV,3,3,11,13,13,328,20,10,12,043,11,03,09,249,22*42
$GPRMC,152917.000,A,5317.5456,N,00614.3536,W,0.37,77.42,220908,,*29

The specification for the NMEA messages are available on the Internet in many places, although they are apparently copyrighted by NMEA, so I won't post them here. For example, you can find the messages relevant to GPS at the end of many of USGlobalsat's manuals.

The PERL script can be used to decode either real RS232 or logic-level serial, at any baud rate. Just change the vales of the configuration variables in the script to reflect what you need.

That's all for now. I'm not sure what I'll have to write about next time as I don't have any of my electronics gear with me, it's stuck on a boat somewhere between L.A. and here.