Question
Can you help me improve what I’ve done to create an enhanced-color picture from an image provided by NASA’s JunoCam? [My work is shown in the penultimate image of Jupiter in this post.]
I’d particularly like to know how to obtain better fine detail while significantly reducing grain—equal to or better than what can be seen in the image shown at the end (posted to the Juno site by David Marriott), which shows a very nice combination of detail, smoothness, and clarity, and is (IMO) pleasingly glossy. [By comparison, my current result has somewhat poorer fine detail, and much more grain.] But I'm open to seeing whatever anyone else comes up with and, more broadly, I’d like to learn of better approaches to this task than what I’ve used. I tried using variations on code shown in answers to other questions about image processing, but was unable to find anything that helped me with this problem.
I played with several different Mathematica image-processing functions, finally settling on the sequence given below. But I’m new to Mathematica’s image-processing capabilities, so I look forward to learning what more experienced hands can accomplish. [I'm particularly interested to see what can be done using the individual color channels, rather than the combined image I worked with.] I’d also be interested to learn how Mathematica’s capabilities, ease-of-use, and general suitability for this work compare with those of specialized image-processing software, like Photoshop.
Background Info. on JunoCam Images, and Test Case
JunoCam is the public-outreach wide-field visible-light camera on NASA’s Juno Jupiter orbiter. It uses a pushframe imager, which means it generates separate R, G, and B image strips that can then be assembled into spatially composited images. When you download, from the JunoCam website, the files associated with an imaging pass, you get a folder containing the following:
1) A “raw” png image containing all these individual strips.
2) Three assembled png images (R, G, and B), in which NASA has stitched together the strips for each color channel.
3) A “map projected” png image, which combines the three color-channel images into one.
More technical info. on JunoCam is available here; select "About JunoCam Images": https://www.missionjuno.swri.edu/junocam/processing
I suspect that essentially no one bothers working with #1, instead letting NASA do the work of stitching the images together. That’s certainly my choice. The options are then to work with either the individual R, G, and B files, or to work with the combined map projected file. I tried the former and had no luck, so instead used the latter.
For my test case, I’m using the Southern Timelapse Sequence, Mission Phase PERIJOVE 10, from 12/16/2017. It can be downloaded here: https://www.missionjuno.swri.edu/junocam/processing?id=JNCE_2017350_10C00038_V01
Additionally, here’s some nice general background on image-processing approaches for these files (using specialized image-processing software, not Mathematica) provided by Jim Plaxco on his Artsnova website: http://www.artsnova.com/Juno-JunoCam-Image-Processing.html
And there's also this from Jesse Dohmann at Wolfram itself: http://blog.wolfram.com/2018/01/12/slicing-silhouettes-of-jupiter-processing-junocam-images/
Mathematica Code
I renamed the map projected png image as “mapprojected.png”, and ran the following code. This yields the image shown under "Final Result."
img = Import["~path_to_file/mapprojected.png"]
imgS = ImageAdjust[Sharpen[img, 100], .4] (*Need to sharpen before converting to HSB, since sharpening doesn't work with HSB; note that here we're also increasing the contrast (using a value of 0.4)*)
imgH = ColorConvert[imgS, "HSB"];
imgA = ImageApply[# {1.03, 2.2, 1.1} &, imgH] (*Adjusting hue, saturation, and brightness, respectively*)
imgP = ImagePad[imgA, 600];
imgR = Rotate[imgP, -.23 Pi] (*Have to use Rotate instead of ImageRotate b/c the latter doesn't support HSB images: “”.*)
In summary, I significantly increased the sharpness, contrast, and color saturation, and modestly increased the brightness. Since I shifted the hue only slightly (towards blue), I'd characterize this as an enhanced-color, rather than false-color, image.
Other attempts:
I tried improving sharpness/reducing grain by instead using ImageDeconvolve (experimenting with various methods and kernels), as well as Blur (computing an unsharp mask), but none of these gave me an improved result over Sharpen:
ImageDeconvolve[img, Normalize[DiskMatrix[a], Total[#, 2] &], Method -> "Wiener"]
ImageDeconvolve[img, GaussianMatrix[a], Method -> "Wiener"]
ImageDeconvolve[img, GaussianMatrix[a]]
ImageDeconvolve[img, Normalize[DiskMatrix[a], Total[#, 2] &], Method -> {"Hybrid", "Preconditioned" -> True}, MaxIterations -> 500]
img2 = img - Blur[img, 100]; (*"compute unsharp mask"*)
img + 4 img2 (*"add unsharp mask to original image"*) (*quotes are from Wolfram documentation*)
Wolfram's documentation for ImageDeconvolve explains: "A kernel used for deconvolution is often referred to as a 'point spread function' (commonly abbreviated 'psf') and is assumed to model the blur whose removal from an image is being attempted. If the point spread function does not match the blur actually present in an image, deconvolution will fail to recover details and may even add spurious artifacts." Alas, I don't have any experience choosing appropriate blur kernels, so I just experimented blindly; but perhaps there is a way to analyze the image to determine which is the best method and kernel to use.
In addition, I tried first upsampling the image (experimenting with various methods), and then repeating all the above attempts but, again, didn't improve the result. [Interestingly, this changed the color and contrast, so I had to adjust for this in my subsequent code.]:
ImageResize[img, Scaled[4], Resampling -> {"CatmullRom"}]
ImageResize[img, Scaled[4], Resampling -> {"Lanczos", 20}]
ImageResize[img, Scaled[4], Resampling -> {"Connes", 8, 2}]
Starting Point: "Map Projected" Image Provided by NASA
Final Result
Here I took the image produced by the above code, and then cropped and padded the bottom. I had to do this final cropping & padding (cropping the bottom to get a straight line, and then padding the bottom with a black border) outside of Mathematica, rather than use ImageCrop, for the same reason I couldn’t use ImageRotate: ImageCrop doesn’t support HSB images. Please let me know if there’s a way to get around these limitations.
Comparison with Another Image Processing Approach
Here’s work done on the same image, that was posted to the Juno site by David Marriott (https://www.missionjuno.swri.edu/Vault/VaultOutput?VaultID=13520&t=1528468966). I don’t know what image-processing software he used. Note that his image has better fine detail than mine, yet is smoother and has significantly less grain:
Here's a detail shot comparing Marriott's work with mine, updated with the results from Carl Lange and halirutan: