## Estimating image sharpness via cusp autocorrelation

Summary

I have some preliminary results from trying Eliot's idea of using the cusp autocorrelation to estimate image sharpness. The basic idea is that the autocorrelation should be narrower and fall off more steeply for sharper cusps/images, and broader and fall off more gradually for blurry cusps/images. Although this sounds good, in practice the autocorrelation seems to fall off with about the same steepness for all images, regardless of cusp sharpness, although there may yet be some other measure of the result that pairs well with what are obviously good and bad cusp subimages. Either way, this technique seems to push the distinguishing intelligence into evaluating a 1d curve or some other statistic of a different sharp or blurry image, in this case the autocorrelation rather than the original image. This is similar to what eventually happens in my other sharpness estimate which makes use of image energy in different spatial frequency bands, although in this case the resulting 1d curves actully do look somewhat different for different images. It may be possible to combine these two techniques, and look at the energy per frequency in just the cusps, as they are quite visually different from one another, although whether they can be ranked in accordance with the perceived sharpness of the rest of the image is yet to be determined.

To estimate the cusp sharpness, first the cusps have to be found:

The general procedure is:

1. Using the circle estimate from 'brightalign.py' or some other means, look at the radii at different angles and calculate the number of peaks above a certain threshold value, typically 0.5 of the maximum value on the circle. Setting this value too high yields multiple spurious estimates for the location of the cusps, and setting it too low gives false positives in the interior of the planet.
2. Look for locations in the radial array where the number of detected peaks goes from 0 to >0 (in either angular direction around the limb).
3. Find the location of the single maximum peak on these radii, or the average location of multiple peaks.
4. If there are more than one candidate in each half-circle (i.e. within 90 degrees of one another), average them into a single candidate.
5. For 5 iterations, move each candidate to the location of the centroid of a +-10 pixel neighborhood in x and y. Since the cusps are usually not the brightest part of the limb, this has the effect of better centering the cusp within a small rectagle.

Example:

```Peaks:
[2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2
3 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 3 2 2 2 2 2 2 2 2 2 2 2]
Candidates:
194.00      69.00   1
199.00     236.00   1
Set1:
194.00      69.00
Set2:
199.00     236.00
Centroid 1 at (2.09, -0.74)
Centroid 2 at (2.36, -1.41)
Centroid 1 at (1.80, -0.55)
Centroid 2 at (2.07, -0.76)
Centroid 1 at (1.37, -0.75)
Centroid 2 at (1.63, -0.96)
Centroid 1 at (1.22, -0.44)
Centroid 2 at (1.23, -0.69)
Centroid 1 at (1.06, -0.15)
Centroid 2 at (1.09, -0.36)
Cusps:
194.41      66.64
197.99     238.69
```

Here are plots of the circumferential values (0 to 360 degrees CCW from +x axis) of the limb at the two radii of the cusps shown above. The top cusp is the first peak in the left plot, the bottom cusp is the second peak in the right plot:

Here are the radial values for the two cusps:

To estimate sharpness, the cusp autocorrelation is performed directly (i.e. no FFT), and values outside of the subimage are set to zero (i.e. no additional background or wrapping, otherwise the peak of the result is not at the center of the autocorrelation, since the maximum value of the cusp is usually toward the sun, and the limb steadily increases in brightness outside of the cusp). The result is normalized so that the peak value is 1.0. Maxima are shown in red in all 4 subimages. The falloff curves are the average values of the result at different distances from the center to the corners of the autocorrelation. Shown below are 3 pairs of {sharp, blurry} images in which the cusps are obviously of different quality. However, the falloff curves appear to be about the same for all images, although the minimum and mean values of the autocorrelation are slightly different for the sharp and blurry images:

```Cusps at:
(194.41, 66.64)
(197.99, 238.69)
Cusp 1 max at:   (49, 19)
Autocorr max at: (25, 25)
Autocorr max=       1.000000 min=       0.118242 mean=       0.468214 sum=    1217.824786
Cusp 2 max at:   (46, 9)
Autocorr max at: (25, 25)
Autocorr max=       1.000000 min=       0.098920 mean=       0.469243 sum=    1220.499815
```

```Cusps at:
(192.89, 65.67)
(198.70, 239.67)
Cusp 1 max at:   (36, 6)
Autocorr max at: (25, 25)
Autocorr max=       1.000000 min=       0.144553 mean=       0.517778 sum=    1346.740421
Cusp 2 max at:   (30, 26)
Autocorr max at: (25, 25)
Autocorr max=       1.000000 min=       0.115161 mean=       0.508130 sum=    1321.645634
```

```Cusps at:
(194.59, 66.60)
(197.38, 238.83)
Cusp 1 max at:   (26, 22)
Autocorr max at: (25, 25)
Autocorr max=       1.000000 min=       0.130670 mean=       0.491402 sum=    1278.137187
Cusp 2 max at:   (29, 26)
Autocorr max at: (25, 25)
Autocorr max=       1.000000 min=       0.105441 mean=       0.484441 sum=    1260.031679
```

```Cusps at:
(192.80, 65.82)
(199.00, 239.49)
Cusp 1 max at:   (30, 16)
Autocorr max at: (25, 25)
Autocorr max=       1.000000 min=       0.146589 mean=       0.516126 sum=    1342.443915
Cusp 2 max at:   (25, 22)
Autocorr max at: (25, 25)
Autocorr max=       1.000000 min=       0.105316 mean=       0.492531 sum=    1281.072660
```

```Cusps at:
(193.71, 66.46)
(198.72, 238.94)
Cusp 1 max at:   (46, 1)
Autocorr max at: (25, 25)
Autocorr max=       1.000000 min=       0.123111 mean=       0.469569 sum=    1221.347879
Cusp 2 max at:   (43, 25)
Autocorr max at: (25, 25)
Autocorr max=       1.000000 min=       0.098441 mean=       0.468849 sum=    1219.477357
```

```Cusps at:
(191.47, 66.57)
(200.50, 239.27)
Cusp 1 max at:   (29, 19)
Autocorr max at: (25, 25)
Autocorr max=       1.000000 min=       0.139014 mean=       0.509251 sum=    1324.562185
Cusp 2 max at:   (49, 27)
Autocorr max at: (25, 25)
Autocorr max=       1.000000 min=       0.109007 mean=       0.492253 sum=    1280.349096
```

Although there are visual differences in the autocorrelation results, it is not clear how to gauge them in order to rank sharpness. One possibility is to look at the asymmetry of the autocorrelation as an indication of sharpness, since the sharper cusps appear to have falloffs that differ in the radial and tangential directions, while the blurrier cusps appear to have more radially symmetric autocorrelations.

Compare the above plots to one shown here for estimating sharpness based on image energy in different spatial frequency bands:

```512 - 64: 0.88300450
64 - 32:  0.08096362
32 - 16:  0.02752120
16 - 8:   0.00493430
8 - 4:    0.00219123
4 - 2:    0.00138515
sharpness = 0.00712553
```

I have yet to port the Qt sharpness code to Wx, but perhaps that should be my next task so that the frequency and autocorrelation methods can be compared using only the cusps as input.