Napisałem sobie taki krótki program do robienia zdjęć z kamerki, gdzie potem sklejam z tego timelapse, ale nie rozumiem jednej rzeczy - zdjęcia zapisują się... z opóźnieniem. Musiałem dolać ukorzeniacza do awokado, więc zabierałem je sprzed kamerki. Po skończonej robocie (9:47) usiadłem do kompa i sprawdziłem poprzednie zdjęcia czy ustawiłem rośliny w miarę w tych samych miejscach. A tu się okazuje, że zdjęcie które powinno być zrobione w momencie skończenia, to tak naprawdę zdjęcie sprzed kilku minut. Łącznie zajęło mu 8 minut (5 zdjęć), zanim dotarł do momentu w którym skończyłem. Dlaczego tak jest? Czegoś tu nie rozumiem?
Kod:
import cv2
from time import sleep
from datetime import datetime

cam = cv2.VideoCapture(0)
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080.0)
cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1920.0)
cam.set(cv2.CAP_PROP_AUTO_WB, 0.0)
cam.set(cv2.CAP_PROP_WB_TEMPERATURE, 7000)
cam.set(cv2.CAP_PROP_SATURATION, 75)
cam.set(cv2.CAP_PROP_CONTRAST, 100)
while True:
   retval, frame = cam.read()
   dt = datetime.now()
   ts = int(datetime.timestamp(dt))
   if retval != True:
      print(str(dt) + ": Can't read frame")
      sleep(5)
      continue
   cv2.imwrite(str(ts) + '.png', frame)
   print(str(dt) + ": saved img " + str(ts) + ".png")
   sleep(120)
#python #programowanie
9e52353b-adf4-4507-b0d0-c53a4af049de
298ca152-8de6-486d-ab2f-5cfddaf7e444
203129d3-d0a7-4a2a-94e6-ee680a320cc4
edbf2503-175a-452d-b48e-c86cd23ecdf2
50e6dc6b-50c7-4419-9057-a4faaeedf354
markxvyarov

@Bielecki Mam uwagę dot. retval, źle ją używasz. Zapisywanie obrazu jest niezależne od wartości retval. Do cyklicznego robienia zdjęć polecam Advanced Python Scheduler.


Polecam zrobić test szybkości wykonania jednego cyklu.

psalek

@Bielecki domyślnie cam.read odczytuje pierwszą ramkę z bufora a nie najświeższą.

Widziałem dwa rozwiązania. Jedno to osobny wątek do porzucania starych ramek: https://stackoverflow.com/questions/43665208/how-to-get-the-latest-frame-from-capture-device-camera-in-opencv


Drugie to wymuszenie porzucenia ramek bezpośrednio przez cv2. To chyba było przez set property ale tak na szybko nie mogę tego znaleźć.


Oba mi działały. To drugie jest wydajniejsze ale w Twoim przypadku oba powinny być ok.

Prucjusz

@Bielecki cv2 działa bardzo wolno. Spróbuj z numpy.

Jesli dobrze pamiętam, z obiektu cv2 można wyciągnąć tablicę numpy i za jego pomocą to zapisać do pliku.

Bielecki

@markxvyarov dlaczego tak uważasz? Jeśli retval będzie false, to kontynuuję loop, żeby nie wywalać całego programu, ale nie zapisuję obrazu


@Prucjusz najwolniejsze w opencv w moim przypadku jest inicjalizowanie kamery przez cv2.VideoCapture(0). Ja loopuję się już po inicjalizacji, nie zwalniam kamery. Sam zapis odbywa się w ciągu ~0,1s, zakładając że sleep trwa równe 120s (takie mam różnice w timestampach).


@psalek dzięki, to mi wiele powiedziało. Wygląda na to że to właśnie bufor. Niby mogę zastosować te rozwiązania (choć porzucanie ramek przez opencv z tego co znalazłem odbywa się poprzez ustawianie odpowiednich properties kamery i nie jestem pewien czy 1. jest to wspierane przez mój model, 2. jest to nadal w opencv, bo gdzieś była wzmianka, że to usunęli), ale to w sumie byłaby sztuka dla sztuki - a w moim przypadku rozwiązanie się w sumie sprawdza. Zwyczajnie mnie ciekawiło dlaczego tak się dzieje i mam odpowiedź. Dzięki

GrindFaterAnona

@Bielecki czym to potem składasz w filmik?

Bielecki

@GrindFaterAnona ffmpeg na wsl (bo na windowsie nie działa globbing, trzeba jakoś kombinować, mi było łatwiej to odpalić na wsl):

`ffmpeg -hwaccel cuda -hwaccel_output_format cuda -framerate 60 -pattern_type glob -i '*.png' -c:v hevc_nvenc -gpu any -rc vbr -cq 28 out.mp4`

Tu akurat z akceleracją gpu, jeśli masz nvidię 1xxx lub nowszą to powinno działać, na AMD się nie orientuję - ale zawsze można wywalić parametry hwaccel i przeliczać procesorem.

Zaloguj się aby komentować