Wolfram Computation Meets Knowledge

Fixing Bad Astrophotography II: Imaging Mars with Mathematica

The planet Mars comes into opposition, the point closest to the Earth, about every 780 days, or a bit over two years. The Martian opposition this year was on April 9. This past May, on a rare clear, warm night, I attempted to capture some images of the red planet. Unfortunately once I had my telescope set up, Mars had passed behind a large tree, so the images I captured were distorted by tree branches. Nevertheless, I did manage to capture a set of frames, and hoped that image processing with Mathematica could produce something usable.

Even without the effect of tree branches, Mars is a difficult planetary target because it is small, and atmospheric turbulence can make shooting it a process of capturing a lot and hoping for the best during those moments when the air stabilizes enough to provide a clear view.

Before the days of photographic imaging, astronomers would sketch Mars at the eyepiece of their telescope, waiting for moments of atmospheric clarity before adding to their drawings. Unfortunately this technique sometimes resulted in features being added to the planet that did not actually exist.

Now the standard way to process planetary images like this is to take a bunch of short exposures and then normalize and stack the collection, weeding out the obviously bad frames. This process increases the signal-to-noise ratio of the final image.

I initially collected my images using software specific to my CCD camera. Here is the path to my collection of Mars exposures in the standard astronomical FITS format.

The first step was to import the collection into Mathematica. With marsPath set to a directory containing the images, I imported the entire set:

Import collection into Mathematica

All the images were now in an easy-to-manipulate list. Wolfram Language is a powerful functional programming language, which allowed me to perform image processing by mapping pure functions onto elements of this list instead of writing looping code.

Each frame of my FITS files consisted of a sublist of three color channels, one for red, green, and blue.

Sublist of three color channels

I needed to convert them to combined color first, which was done by just mapping the ColorCombine function onto each image in the list:


As Mars occupies only a small portion of the frame, I cropped the image to 200 pixels wide, so time wouldn’t be spent processing uninteresting pixels.

Image cropping

Here is what the array of cropped images looked like:

Array of cropped images
Array of cropped images

As you can see, Mars was moving around a lot due to atmospheric turbulence, and because of that and the movement of the tree branches, I needed to align the images before combining them. Fortunately Mathematica can do this automatically. Here I specified that only a translation transformation should be applied to each image, otherwise ImageAlign might try to rotate the images if it got confused. The subsequent line filtered out all the cases where ImageAlign failed to find a successful transformation because the image was just too fuzzy.

Aligning images

The FITS images I collected were 16-bit images. They needed to be represented by a more fine-grained data type before doing scaling and arithmetic on the images. Otherwise, I would get banding, and fine detail would have been washed out. In order to prevent this effect, I converted them to use 64-bit real values.

Convert using 64-bit real values

This was the resulting array of aligned images:

Resulting array of aligned images
Resulting array of aligned images

Every time I image things like this, I need to eliminate the “clinker” images—ones that are too fuzzy to add to the stack. To sort them out, I created a table of the images I was going to use, initialized to True.

Create table of images to use

It was easy to spin up a quick UI to allow me to sort out the clinkers.

Remove "clinker" images
Remove "clinker" images

The useTable array could then be used to pull out the good images in one step.

useTable array

To combine the good images into a single image with an improved signal-to-noise ratio, I took their statistical median using the Median function.

Using Median function

Of course, it is completely trivial to get the Mean of the image list as well, and it is sometimes good to see how the Mean image compares to the Median image. Other statistical functions, like TrimmedMean, could also have been used here.

Using Mean function

The final adjustment sharpened the image and brought down the brightness while bringing up the contrast.

Final adjustment

Not bad, considering the quality of the initial frames.

Mathematica provided all the tools I needed to easily import, prepare, align, combine, and adjust fuzzy planetary images taken through tree branches in my back yard to yield a decent amateur image of Mars.

Download this post as a notebook (.nb) file or CDF (.cdf) file.
Download the compressed (.zip) accompanying Flexible Image Transport System (FITS) files (Note: This file is over 100 MB).


Join the discussion

!Please enter your comment (at least 5 characters).

!Please enter your name.

!Please enter a valid email address.


  1. Nice post. Instead of Sharpen you can also use ImageDeconvolve and try various methods it supports. You can get a clearer image sometimes.
    I think there is a mistake towards the end, you posted the Median screenshot twice.
    How many images were in the stack initially and with how many did you create the final image?

  2. What kind of results could I expect using a Canon 1100D and a 6″ Newt mounted on a EQ5 Pro?

    many thanks