basler / pypylon

The official python wrapper for the pylon Camera Software Suite
http://www.baslerweb.com
BSD 3-Clause "New" or "Revised" License
540 stars 209 forks source link

camera.AcquisitionFrameRate.SetValue() is not accurate #748

Open da9da9 opened 2 months ago

da9da9 commented 2 months ago

Describe what you want to implement and what the issue & the steps to reproduce it are: Framerate issue

I am trying to capture a sequence of still images.

I set two stages as below. I checked that 500fps is possible from the pylon viewer.

    camera.StartGrabbing(pylon.GrabStrategy_LatestImages, pylon.GrabLoop_ProvidedByUser)
    camera.AcquisitionFrameRateEnable.SetValue(True)
    total_frames = [50, 50]  # Frames at different stages
    frame_rates = [500, 10]  # Corresponding frame rates

And I set the framerate as below. and started recording.

    camera.AcquisitionFrameRate.SetValue(frame_rates[0])

    height = camera.Height.GetValue()
    width = camera.Width.GetValue()
    image_Array_0 = np.empty(shape=(height, width, total_frames[0]), dtype=np.uint8)
    image_Array_1 = np.empty(shape=(height, width, total_frames[1]), dtype=np.uint8)
    while camera.IsGrabbing():
        grabResult = camera.RetrieveResult(5000, pylon.TimeoutHandling_ThrowException)
        camera.AcquisitionFrameRate.SetValue(frame_rates[0])
        if grabResult.GrabSucceeded():
            image = converter.Convert(grabResult).GetArray()
            cv2.imshow('Live View', image)

            if recording == True:
                ts = time.time()
                print(ts)
                print("recording started")
                for i in range(total_frames[0]):
                    with camera.RetrieveResult(5000) as result:
                        if grabResult.GrabSucceeded():
                            image_Array_0[:, :, i] = result.Array
                            ts = time.time()
                            print(ts)
                        else:
                            print(grabResult.ErrorDescription)
                camera.AcquisitionFrameRate.SetValue(frame_rates[1])
                print("stage1 finished")
                time.sleep(1/frame_rates[1])
                current_stage = 2
                for j in range(total_frames[1]):
                    with camera.RetrieveResult(5000) as result:
                        if grabResult.GrabSucceeded():
                            image_Array_1[:, :, j] = result.Array
                            ts = time.time()
                            print(ts)
                        else:
                            print(grabResult.ErrorDescription)
                recording = False
                captured = True
                ts = time.time()
                print(ts)
                print("recording finished")
                camera.StopGrabbing()

and below is the time difference between each frame

Stage1 (ms)     Stage2 (ms)
1.509904861     1.999855042
1.019954681     0.990152359
0000000000      0.999927521
0000000000      96.17996216
1.000165939     99.92003441
0000000000      99.99990463
1.080036163     99.81012344
2.009868622     99.97987747
3.000020981     100.8000374
0.98991394      99.17998314
2.530097961     99.98011589
2.01010704      100.2399921
1.999855042     100.219965
1.460075378     99.94006157
2.00009346      99.2898941
2.009868622     100.219965
2.00009346      99.97010231
1.989841461     100.3201008
2.00009346      99.65991974
2.079963684     100.2500057
2.660036087     100.6000042
1.260042191     99.07984734
1.999855042     100.1400948
2.350091934     99.81989861
1.71995163      100.4400253
2.00009346      100.0401974
1.929998398     99.47991371
1.999855042     99.92003441
2.390146255     100.0299454
1.519918442     100.5599499
2.089977264     99.43008423
2.089977264     99.95985031
1.640081406     99.98011589
2.259969711     100.1200676
2.01010704      100.4998684
2.169847488     99.32994843
1.830101013     100.2800465
2.009868622     99.35998917
2.75015831      100.8901596
1.749992371     99.13992882
1.489877701     101.0200977
2.00009346      99.18999672
2.009868622     100.9399891
1.99007988      98.98996353
2.140045166     100.4199982
2.009868622     99.43985939
1.550197601     100.0201702
3.010034561     100.0199318
2.009868622     100.4700661

As you can see, the stage 1 which is fast framerate is not very consistent. It must be near 2ms, but they are in the range of 1~3ms and sometimes it is even 0ms or more than 3ms Also, the relatively slow stage 2 shows the initial framerate is very fast. and it reaches to the specified framerate.

Is my method of specifying the framerate wrong?

Is your camera operational in Basler pylon viewer on your platform

Yes

Hardware setup & camera model(s) used

acA1920-150uc USB3 communication with PC.

Runtime information:

OS is windows 11 

pylon Viewer 64-Bit
pylon Release 7.4.0.14900
pylon C++ SDK 7.4.0.38864
pylon Application 2.1.0.14100
pylon Viewer 7.4.0.14100

python: 3.11.7 | packaged by Anaconda, Inc. | (main, Dec 15 2023, 18:05:47) [MSC v.1916 64 bit (AMD64)]
platform: win32/AMD64/10
pypylon: 3.0.1 / 7.4.0.38864
SMA2016a commented 2 months ago

it is not clear for me what time you want to measure? it seems to be for me that the measurement is not stable on your PC in highspeed mode.

how affect his your application? did you check the timestamp if grab result? also print block ids to see if the system loses images

thiesmoeller commented 1 month ago

As mentioned by @SMA2016a you measure the time when you receive the frame on your host and not when the acquisition took place.

As you are not running on a RTOS, the time when your user process wakes up ( RetrieveResult returns ) can jitter quite heavy depending on overall system load.