Examining frames while capturing?

Discussions on extending SharpCap using the built in Python scripting functionality
Post Reply
FlankerOneTwo
Posts: 22
Joined: Sun Feb 25, 2024 6:14 pm

Examining frames while capturing?

#1

Post by FlankerOneTwo »

Hi,
Random question, as I'm doing some scripting to automate SHG-700 captures. Is there a way to examine frame data such as min or mean values while capturing a video sequence? Ideally I'd like to be able to start the mount moving, capture, and then automatically stop the capture when the scan passes the opposite end of the solar disk. IIRC, the histogram updates during the capture, so I think SharpCap is seeing this data somewhere. Doesn't have to be terribly fast, even checking twice a second would be enough.

Thanks!
Jean-Francois
Posts: 822
Joined: Sun Oct 13, 2019 10:52 am
Location: Germany

Re: Examining frames while capturing?

#2

Post by Jean-Francois »

Hello,

Yes, you can.
Have a look at my script here: viewtopic.php?t=8195

Or here a short part:

Code: Select all

def framehandler(sender, args):
    global dumpdata
    if (dumpdata):
        try:
            cutout = args.Frame
            Stat = cutout.GetStats()
            print(Stat.Item1)
            print(Stat.Item2)                
        except:
            print("Problem framehandler")

...
dumpdata = True
SharpCap.SelectedCamera.FrameCaptured += framehandler  
...
dumpdata = False
SharpCap.SelectedCamera.FrameCaptured -= framehandler
...             
The "Item1" and "Item2" are the average and the standard deviation on the full frame.
If you want you can define a ROI zone (= red rectangle).

The "SharpCap.SelectedCamera.FrameCaptured" will start the "framehandler" each time a new image is captured.
You can add a counter somewhere and take only 1 from x frames.

Regards,
Jean-Francois
FlankerOneTwo
Posts: 22
Joined: Sun Feb 25, 2024 6:14 pm

Re: Examining frames while capturing?

#3

Post by FlankerOneTwo »

Thanks very much, I think that will do exactly what I want!
Is there a detailed scripting reference somewhere that fully describes the Object model and methods available? I don't seem to have been able to locate one googling around.
Jean-Francois
Posts: 822
Joined: Sun Oct 13, 2019 10:52 am
Location: Germany

Re: Examining frames while capturing?

#4

Post by Jean-Francois »

Hello,

No description of the object model or other methods.
You must search yourself when it concern C#/.NET topics ... or ask Robin with more detailed question about the SharpCap functions.

Jean-Francois
User avatar
admin
Site Admin
Posts: 17342
Joined: Sat Feb 11, 2017 3:52 pm
Location: Vale of the White Horse, UK
Contact:

Re: Examining frames while capturing?

#5

Post by admin »

Hi,

there are some basics in the 'Scripting' section of the user manual (https://docs.sharpcap.co.uk/4.1/#!2!Scripting) and also more info can be found on many topics in this section of the forums. It's also worth remembering the Python 'help' function which will at least describe the parameters needed by an API call for you or list the API available on an object. Finally, because it is sometimes hard to find the types needed as API parameters, there is a helper method to make this easier...

Code: Select all

>>> SharpCap.FindScriptingType('CaptureLimitType')
"'CaptureLimitType' could be one of :\r\nSharpCap.UI.CaptureLimitType in SharpCap.Interfaces\r\n"
This lets you search for a type by name, and you get back the assembly that you need to clr.AddReference (SharpCap.Interfaces in this case, but that is probably already done for you by default) and the type you need to import ('import CaptureLimitType from SharpCap.UI').

cheers,

Robin
FlankerOneTwo
Posts: 22
Joined: Sun Feb 25, 2024 6:14 pm

Re: Examining frames while capturing?

#6

Post by FlankerOneTwo »

Hi Robin,
Thanks, I'm mostly finding things by googling around, just some items like how the frame handler and events work were a little difficult to find.
I do have a few more questions at the moment -

1. is there a way to find the capture frame rate for the LivePreview without having to grab it from the notification text? It doesn't seem to be in the SharpCap.SelectedCamera.LatestStatus that I can find, and I can't find a specific method to determine if the camera is in a mode where the fps counter is known to definitely be displayed in the notification text. The fps indicator appears to come on at some point when SharpCap sees a high enough frame rate? but just checking whether the camera is in LiveView with an exposure time shorter than xxx doesn't seem to work reliably.

2. I had thought that StopCapture() would block until all buffered frames were completely written, but the SHG script does appear to be starting the return slew before this happens. Are either SharpCap.CanDeleteLastOutput() or SharpCap.SelectedCamera.CanCapture() a reliable means of determining that the all the buffered frames have been written? It does seem that over time the buffer is not completely emptying between consecutive sequences, because the sequences that I can acquire before frame buffering kicks in seems to get shorter and shorter.

Thanks!
User avatar
admin
Site Admin
Posts: 17342
Joined: Sat Feb 11, 2017 3:52 pm
Location: Vale of the White Horse, UK
Contact:

Re: Examining frames while capturing?

#7

Post by admin »

Hi,

SharpCap in general only keeps track of the frame rate to display in the status - for most astronomy cameras, the frame rate is something that you observe by seeing how often frames arrive rather than something that is directly controlled. One of three things tends to limit the frame rate for a given camera/setup

1) The exposure - at 50ms exposure, you cannot get more than 20fps
2) How long is taken to transfer a frame from the camera to the PC - if that takes 100ms then you cannot get more than 10fps
3) Any fundamental limits of the camera sensor itself (if neither of the first two are lower).

Anyway, right now there isn't a good way in scripting to get the current frame rate as displayed in the status, but the camera object does the tracking, so I will see if I can make it available via SharpCap.SelectedCamera.FrameRate.

As to StopCapture, a simple call to 'StopCapture' should not return until all frames have been written and the file finalised and closed. Is the SHG script calling the 'async' version (StopCaptureAsync) instead? That version returns an awaitable task that will signal that it is complete when the StopCapture process is done, but allows the script to carry on with other things while waiting.

cheers,

Robin
FlankerOneTwo
Posts: 22
Joined: Sun Feb 25, 2024 6:14 pm

Re: Examining frames while capturing?

#8

Post by FlankerOneTwo »

Hi,

Thanks for the feedback! I just put in a bit of code at the start of the script to measure the capture rate for a second, so not a definite need for you to spend time putting time into that.

The script just calls StopCapture, not the async version. Hmm. Another possibility is that there is enough solar drift during the buffered writes that the mount is just out of alignment with the sun. In any case, I've rewritten the script to look for the edges of the sun for positioning, and that in conjunction with a faster laptop/NVME drives seems to have solved that problem.
Jean-Francois
Posts: 822
Joined: Sun Oct 13, 2019 10:52 am
Location: Germany

Re: Examining frames while capturing?

#9

Post by Jean-Francois »

Hello,

In my "INTI" script for the scan and capture of the SHG, I added in the past the function to measure the frame rate ... by taking a short film and then by searching the frame rate information from the "CameraSetting.txt" file.
It is not a simple command call of the frame rate (Robin explained that no direct script function exists).
The advantage of the method is the measured frame rate take in account all the chain of the transfer up to the saving.
The only small difference is the test capture is short. Maybe a longer capture time (1 minute or longer) will show some problem on the side of the hard drive or SSD.

Note that the following script calculate the optimal mount scanning rate from the camera "framerate" and other parameters.

Code: Select all

    def framerate(self, sender, event):
        def Log(text):
            self.process.Log(time.strftime("%H:%M:%S") + " - " + text)

        Film_Output = SharpCap.SelectedCamera.Controls.OutputFormat.Value
        if (Film_Output == 'SER file (*.ser)' or Film_Output == 'AVI files (*.avi)'):
            print("Film format OK")
        else:
            MessageText = "The Output Format is not SER or AVI.\n\nChange the Output Format in the Camera Controls."
            MessageBox.Show(MessageText, "SHG", MessageBoxButtons.OK, MessageBoxIcon.Error)
            self.FrameButton.Text = "Frame Rate"
            self.FrameButton.BackColor = Color.Gainsboro
            return()

        self.FrameButton.BackColor = Color.Red
        CameraSettingFile = SharpCap.Settings.CreateCameraSettingsFile
        if (CameraSettingFile == False):
            SharpCap.Settings.CreateCameraSettingsFile = True
            SharpCap.Settings.Save()
        SharpCap.SelectedCamera.PrepareToCapture()
        SharpCap.SelectedCamera.RunCapture()
        time.sleep(2)
        SharpCap.SelectedCamera.StopCapture()
        SharpCap.ShowNotification(None)
        file = SharpCap.GetLastCaptureFilename()
        file_settings = os.path.splitext(file)[0] + ".CameraSettings.txt"
        with open(file_settings, 'r') as fp:
            for l_no, line in enumerate(fp):
                if "ActualFrameRate" in line:
                    break
        parts = line.split("=")[1]
        framerate = float(parts.split("f")[0])
        if (CameraSettingFile == False):
            SharpCap.Settings.CreateCameraSettingsFile = False
            SharpCap.Settings.Save()
        try:
            os.remove(file)
            os.remove(file_settings)
        except:
            print("No file to delete")

        self.FrameButton.Text = "Frame Rate"
        self.FrameButton.BackColor = Color.Gainsboro

        now_JD = AstroUtilities.JulianDateUtc + delta_time
        T = (now_JD - 2451545)/36525
        M = ((-0.00000048*T - 0.0001559)*T + 35999.05030)*T + 357.52910
        C = ((-0.000014*T - 0.004817)*T + 1.914600)*sin(radians(M))
        C = C +(-0.000101*T + 0.019993)*sin(radians(2*M)) + 0.000290*sin(radians(3*M))
        Theta = C + (0.0003032*T + 36000.76983)*T + 280.46645
        ex = (-0.0000001236*T - 0.000042037)*T + 0.016708617
        R = 1.000001018*(1 - ex*ex) / (1 + ex*cos(M + C))*149597870.7                   # Sun-Earth distance [km]
        D = degrees(2 * atan(696342/R))                                                 # Sun diameter [deg]
        Time_1x_sideral = D / 360 * 86400                                               # Time for 1x sun scan
        Epsilon = 23.439291 + ((0.001813*T - 0.00059)*T - 46.815)*T/3600
        Sun_Delta = asin(sin(radians(Epsilon)) * sin(radians(Theta)))                   # Delta coordinate of the sun at the "now date"
        try:
            Binning_Liste = SharpCap.SelectedCamera.Controls.Binning.AvailableValues    # Available binning (1x1, 2x2, ...)
            binning = Binning_Liste[SharpCap.SelectedCamera.Controls.Binning.Bin - 1]   # Selected binning
        except:
            binning = "1x1"
        N_pixel = 2000 * tan(radians(D/2)) * float(self.TelFocaleTextbox.Text)          # 2000 => 2*1000 => 2*tan()* focal in µm
        N_pixel = (N_pixel * Spectro_ratio) / SharpCap.SelectedCamera.PixelSize.Height
        Scan_Time = N_pixel / framerate
        Tel_scan_rate = Time_1x_sideral / (Scan_Time * math.cos(Sun_Delta))
        Log("Binning = " + binning)
        Log("Pixel size = " + str(SharpCap.SelectedCamera.PixelSize.Height) + " µm")
        Log("Frame rate = " + str("%.1f" % round(framerate,1)) + " fps")
        Log("Sun size = " + str("%.1f" % round(N_pixel,1)) + " pixel")
        Log("Sun delta = " + str("%.1f" % round(math.degrees(Sun_Delta),1)) + " deg")
        Log("Mount scan rate = " + str("%.1f" % round(Tel_scan_rate,1)) + " x")
        print("Mount scan rate = " + str("%.1f" % round(Tel_scan_rate,1)) + " x")

Concerning the StopCapture() not waiting ... in my script and all the imaging I did in the past, the script was all the time waiting until the last image is saved before starting the next scan movement.

Regards,
Jean-Francois
FlankerOneTwo
Posts: 22
Joined: Sun Feb 25, 2024 6:14 pm

Re: Examining frames while capturing?

#10

Post by FlankerOneTwo »

Hi,

Thanks for the response. I hadn't gotten around to testing whether StopCapture() blocked or not; if it does so in your experience, it must be that solar drift was was the cause of the loss of synchronization rather than waiting for buffered frames. It's around 45C here during the day at the moment, so my brain doesn't work well when I'm trying to debug code outside scopeside :D . My newer version of the script looks for the transition over the limb instead of using a fixed acquisition time, which appears to solve the sync issue.

Re: frame rate measurement, with the faster NVME drive the write rate doesn't seem to be much of a factor, so I went the simple route of seeing how much SharpCap.SelectedCamera.LatestStatus.CapturedFrames changes over one second. Seems to be close enough for my rough calculation of required scanning speed simply assuming a 0.5 degree solar diameter and measuring the width of the Sun in the image, and the resulting scan Y:X ratios are close enough to 1 for my purposes. Your scan rate calculation is of course much more precise, I actually don't know if the AM5 can control the slew rate in either axis accurately enough for a more accurate slew calculation to make a difference.

Speaking of which - have you noticed any difference in results in scanning in RA vs Dec? With the SHG mounted in the intuitive direction (camera on top), I'm scanning in RA as in the original provided script. This does result in somewhat more mass moving than if I scan in Dec, although I'm not sure whether the torque moment in Dec is more or less than it is in RA, given the OTA length. I'll have to experiment with that a bit. Mounting the SHG "sideways" _would_ make the micrometers more easily accessible.
Post Reply