Live Collimation Aid
Live Collimation Aid
SharpCap Collimation Overlay
https://github.com/bvalente22/sharpcap- ... on-overlay
An IronPython script for SharpCap Pro that automatically detects a defocused star's donut pattern and draws overlay circles to aid collimation of reflector telescopes. It measures the offset between the outer ring (primary mirror) and inner shadow (secondary mirror) in real time, showing you exactly how far off collimation is and which direction to correct, and updates to keep the defocused star and collimation details updated.
I use sharpcap to collimate my reflector telescopes, but always found it difficult to "eyeball" how accurate is the collimation.
I wanted an live overlay that would find the donut, automatically add circle overlays for the inner/outer portion of the donut, and give some indication of how close they were to being aligned.
This script provides a live overlay that performs this function.
Feedback welcome.
Brian
https://github.com/bvalente22/sharpcap- ... on-overlay
An IronPython script for SharpCap Pro that automatically detects a defocused star's donut pattern and draws overlay circles to aid collimation of reflector telescopes. It measures the offset between the outer ring (primary mirror) and inner shadow (secondary mirror) in real time, showing you exactly how far off collimation is and which direction to correct, and updates to keep the defocused star and collimation details updated.
I use sharpcap to collimate my reflector telescopes, but always found it difficult to "eyeball" how accurate is the collimation.
I wanted an live overlay that would find the donut, automatically add circle overlays for the inner/outer portion of the donut, and give some indication of how close they were to being aligned.
This script provides a live overlay that performs this function.
Feedback welcome.
Brian
- Attachments
-
- example_01.png (283.75 KiB) Viewed 984 times
-
- example_02.png (739.23 KiB) Viewed 984 times
- admin
- Site Admin
- Posts: 17545
- Joined: Sat Feb 11, 2017 3:52 pm
- Location: Vale of the White Horse, UK
- Contact:
Re: Live Collimation Aid
Hi,
thanks for sharing - that looks very cool and highly useful.
I think a good question for me to ask script authors is 'was there anything that you wanted to do but found hard or impossible?' Maybe you have a great idea for some extra feature for this tool but couldn't find a way to make it happen using the current scripting API. If there is anything like that, let me know and I can think about how to it might be made possible in future.
thanks,
Robin
thanks for sharing - that looks very cool and highly useful.
I think a good question for me to ask script authors is 'was there anything that you wanted to do but found hard or impossible?' Maybe you have a great idea for some extra feature for this tool but couldn't find a way to make it happen using the current scripting API. If there is anything like that, let me know and I can think about how to it might be made possible in future.
thanks,
Robin
Re: Live Collimation Aid
Robin
The current API forces scripts to do expensive per-frame work (allocate drawing context, copy pixel buffer, dispose everything) even when nothing has changed. A retained overlay model and direct pixel buffer access would greatly reduce frame rate impact and overhead. some things like
- direct ROI pixel access like (GetRegion)
- Native helpers like GetBrightnessCentroid() or GetPeakBrightness()
- Frame sequencer number
These suggestions are may be unique to my script. I'm somewhat assuming collimation will be used on a small ROI along with features like frame stacking, so frame rate isn't critical, so the end user impact may not be high. But if we do run into frame rate issues, the above will certainly help
Brian
The current API forces scripts to do expensive per-frame work (allocate drawing context, copy pixel buffer, dispose everything) even when nothing has changed. A retained overlay model and direct pixel buffer access would greatly reduce frame rate impact and overhead. some things like
- direct ROI pixel access like (GetRegion)
- Native helpers like GetBrightnessCentroid() or GetPeakBrightness()
- Frame sequencer number
These suggestions are may be unique to my script. I'm somewhat assuming collimation will be used on a small ROI along with features like frame stacking, so frame rate isn't critical, so the end user impact may not be high. But if we do run into frame rate issues, the above will certainly help
Brian
- admin
- Site Admin
- Posts: 17545
- Joined: Sat Feb 11, 2017 3:52 pm
- Location: Vale of the White Horse, UK
- Contact:
Re: Live Collimation Aid
Hi Brian,
there are already solutions to some of these...
Frames already have a sequence number - it's the 'Index' property. It will reset to zero every time SharpCap has to re-initialize the camera (resolution change or bit depth change, etc), but otherwise should increment with each passing frame.
You can get the HistogramData for a frame (frame.CalculateHistogram()) and then ask that for centile values - ask for the 99.9th centile to get something close enough to peak brightness for instance. You can also call CutROI() on a frame to cut out any area for more detailed processing (but don't forget to .Release() the returned copy).
There is not quite a retained overlay, but internally I have a system of frame annotations that are drawn over the frame on the screen when it is displayed - this avoids the conversion to bitmap and drawing on the bitmap overhead. Most of the UI drawn on the image area now uses this approach rather than the older bitmap manipulation approach. The good news is that the API for this is the same as the graphics API that you get via frame.GetDrawableBitmap().GetGraphics(). Use frame.GetAnnotationGraphics() to get the graphics object, then dispose of it when done. (Originally I wrote "The bad news is that you can't get at it from scripting at the moment, but I can resolve that issue if it would help.", but that was wrong)
cheers,
Robin
there are already solutions to some of these...
Frames already have a sequence number - it's the 'Index' property. It will reset to zero every time SharpCap has to re-initialize the camera (resolution change or bit depth change, etc), but otherwise should increment with each passing frame.
You can get the HistogramData for a frame (frame.CalculateHistogram()) and then ask that for centile values - ask for the 99.9th centile to get something close enough to peak brightness for instance. You can also call CutROI() on a frame to cut out any area for more detailed processing (but don't forget to .Release() the returned copy).
There is not quite a retained overlay, but internally I have a system of frame annotations that are drawn over the frame on the screen when it is displayed - this avoids the conversion to bitmap and drawing on the bitmap overhead. Most of the UI drawn on the image area now uses this approach rather than the older bitmap manipulation approach. The good news is that the API for this is the same as the graphics API that you get via frame.GetDrawableBitmap().GetGraphics(). Use frame.GetAnnotationGraphics() to get the graphics object, then dispose of it when done. (Originally I wrote "The bad news is that you can't get at it from scripting at the moment, but I can resolve that issue if it would help.", but that was wrong)
cheers,
Robin
- admin
- Site Admin
- Posts: 17545
- Joined: Sat Feb 11, 2017 3:52 pm
- Location: Vale of the White Horse, UK
- Contact:
Re: Live Collimation Aid
Ah, no I was wrong... You can get at the annotation system from scripting...
Just use
instead of
cheers,
Robin
Just use
Code: Select all
graphics = frame.GetAnnotationGraphics()
// do graphics stuff
graphics.Dispose()Code: Select all
bitmap = frame.GetDrawableBitmap()
graphics = bitmap.GetAnnotationGraphics()
// do graphics stuff
graphics.Dispose()
bitmap.Dispose()Robin
Re: Live Collimation Aid
Thanks Robin, let me look your suggestions more closely. I'm not sure we need to do anything right now, I'd rather see some use of the script and then evaluate if more is needed. Right now it seems to be performing well, but i have limited 'actual use' data.
brian
brian
Re: Live Collimation Aid
Robin -thanks for the API pointers — suggestions implemented, here is some feedback:
GetAnnotationGraphics("key") — working great, noticeably reduces per-frame overhead by eliminating the GetDrawableBitmap/Dispose cycle.
CalculateHistogram() + GetCentilePointsF(99.9) — working. The max across the returned per-channel array is used as the peak brightness estimate. Skips the full-frame pixel loop for peak detection when tracking, which was expensive.
CutROI(Rectangle) — working. Takes a Rectangle object (not 4 separate ints). During tracking, the region is cropped to ~1.5x the outer circle radius and only that region is analyzed, significantly reducing Marshal.Copy buffer size and iteration.
frame.Index — this always returns 2097199 regardless of frame? so it doesn't appear to increment between frames in the handler. Fell back to manual frame counter for the analysis interval. Not a big deal, just wanted to flag the behavior in case it's unintended.
One thing not implemented: retained/persistent overlay annotations across frames. The current GetAnnotationGraphics approach already eliminated most of the drawing overhead. If there's a way to persist annotations across frames without redrawing, that might be somethign to consider.
Overall the script feels more responsive with these changes, particularly the CutROI + histogram combination during tracking mode which avoids both the full-frame buffer copy and the IronPython pixel scan.
Brian
GetAnnotationGraphics("key") — working great, noticeably reduces per-frame overhead by eliminating the GetDrawableBitmap/Dispose cycle.
CalculateHistogram() + GetCentilePointsF(99.9) — working. The max across the returned per-channel array is used as the peak brightness estimate. Skips the full-frame pixel loop for peak detection when tracking, which was expensive.
CutROI(Rectangle) — working. Takes a Rectangle object (not 4 separate ints). During tracking, the region is cropped to ~1.5x the outer circle radius and only that region is analyzed, significantly reducing Marshal.Copy buffer size and iteration.
frame.Index — this always returns 2097199 regardless of frame? so it doesn't appear to increment between frames in the handler. Fell back to manual frame counter for the analysis interval. Not a big deal, just wanted to flag the behavior in case it's unintended.
One thing not implemented: retained/persistent overlay annotations across frames. The current GetAnnotationGraphics approach already eliminated most of the drawing overhead. If there's a way to persist annotations across frames without redrawing, that might be somethign to consider.
Overall the script feels more responsive with these changes, particularly the CutROI + histogram combination during tracking mode which avoids both the full-frame buffer copy and the IronPython pixel scan.
Brian
-
archer1960
- Posts: 98
- Joined: Sun Feb 23, 2025 9:04 pm
Re: Live Collimation Aid
Once we get a decently warm night, I'll give this script a try for my annual collimation tweak...
Re: Live Collimation Aid
Great - let me know what you think, any suggestions welcome.archer1960 wrote: Thu Mar 19, 2026 4:08 pm Once we get a decently warm night, I'll give this script a try for my annual collimation tweak...
Here's a short live (using simulator) demo on how to cycle through the overlay using the menu bar button (upper left):
https://youtu.be/pqtVNEPrlY8
Brian
Re: Live Collimation Aid
@archer1960 please make sure to pull the latest github release right before you test. I did some updates to improve speed and accuracy, will probably continue doing so.
Brian
Brian