OpenCV posiada możliwość odczytywania i zapisywania obrazu w wielu popularnych formatach. Funkcjonalność ta udostępniona jest w zestawie HighGui. Dopuszczalne są (podano rozszerzenia plików):bmp, dib, jpeg, jpg, jpe, png, pbm, pgm, ppm, sr, ras, tiff, tif, exr oraz jp2. Funkcje, które pozwalają przeprowadzić te operacje pojawiały się już w poprzednich wpisach. Dla przypomnienia poniżej zaprezentowano przykładowy kawałek kodu:
Trochę bardziej złożonym zagadnieniem jest odczyt i zapis strumienia wideo. OpenCV pozawala domyślnie na obsługę plików dvix (patrz: źródło). Z obsługą obrazu wideo związana jest analogiczna do IplImage struktura CvCapture. Wyznaję zasadę, że lepszy okomentowany kod niż długie opisy działania ;-) Poniżej przykład pokazujący odczyt i wyświetlanie pliku avi:
Ostatnią funkcjonalnością dzisiaj opisaną będzie zapis wideo. Zapisywać możemy kolejne obrazy IplImage. Nie musi być to zatem obraz z kamery czy przetworzony plik wideo. Przykład:
Jakieś wady? Niestety tak. Nie da się ukryć, że kamerki komputerowe mają zmienny (zależny np. od oświetlenia) współczynnik fps. W CvVideoWriter nie zmienimy tego po utowrzeniu, więc film może zachowywać się nieprzewidywalnie w trakcie nagrywania. Problem nie dotyczy oczywiście zapisu wcześniej przygotowanych statycznych obrazów. Jeżeli ktoś posiada lepszy pomysł na synchronizację obrazu z kamery z nagrywaniem to zapraszam do komentarzy ;-)
// wczytanie obrazu w odcieniach szarosci IplImage*img=cvLoadImage("/home/lukasz/Pulpit/rysowanie.png",CV_LOAD_IMAGE_GRAYSCALE); // zapisanie obrazu do pliku cvSaveImage("/home/lukasz/Pulpit/rysowanie.png",img);
Trochę bardziej złożonym zagadnieniem jest odczyt i zapis strumienia wideo. OpenCV pozawala domyślnie na obsługę plików dvix (patrz: źródło). Z obsługą obrazu wideo związana jest analogiczna do IplImage struktura CvCapture. Wyznaję zasadę, że lepszy okomentowany kod niż długie opisy działania ;-) Poniżej przykład pokazujący odczyt i wyświetlanie pliku avi:
// odczytanie pliku avi CvCapture* vid = cvCreateFileCapture("/home/lukasz/Pulpit/sample.avi"); // tworzymy okno wyswietlajace obraz cvNamedWindow("plik wideo", 0); // odczytanie pierwszej klatki - niezbedne do prawidlowego odczytania wlasciwosci pliku // przy uzyciu funkcji cvGetCaptureProperty cvQueryFrame(vid); // odczytujemy z wlasciwosci pliku liczbe klatek na sekunde double fps = cvGetCaptureProperty(vid, CV_CAP_PROP_FPS); // wyliczamy czas potrzebny do odtwarzania pliku z prawidlowa prędkoscia int odstep_miedzy_klatkami = 1000 / fps; while (true) { // pobranie kolejnej ramki IplImage* ramka = cvQueryFrame(vid); // jezeli nie jest pusta to wyswietlamy if (ramka != 0) cvShowImage("plik wideo", ramka); else break; // czekamy przez okreslony czas int c = cvWaitKey(odstep_miedzy_klatkami); // jezeli nacisnieto klawisz 'k', konczymy wyswietlanie if (c == 'k') break; } // zwolnienie zasobów cvDestroyAllWindows(); cvReleaseCapture(&vid);Kolejnym poruszanym zagadnieniem jest odczyt i zapis obrazu z kamery. Zasadniczo nie różni się on bardzo od obsługi plików dvix. Dalej mamy do czynienia ze strukturą CvCapture. Zmienia się jedynie metoda zwracająca do niej wskaźnik. Przykład:
// pobranie zasobu kamery, parametr mowi o tym ktora kamere wybieramy // w przypadku gdy w systemie dostepna jest wiecej niz jedna CvCapture* vid = cvCreateCameraCapture(0); // tworzymy okno wyswietlajace obraz cvNamedWindow("plik wideo", CV_WINDOW_AUTOSIZE); // odczytanie pierwszej klatki - niezbedne do prawidlowego odczytania wlasciwosci pliku // przy uzyciu funkcji cvGetCaptureProperty cvQueryFrame(vid); // ustalamy wartosc fps - najlepiej wieksza niz maksymalna deklarowana przez producenta // Jezeli wartosc bedzie za mala, obraz bedzie pojawial sie z opoznieniem double fps = 50; int odstep_miedzy_klatkami = 1000 / fps; while (true) { // pobranie kolejnej klatki IplImage* ramka = cvQueryFrame(vid); // jezeli nie jest pusta to wyswietlamy if (ramka != 0) cvShowImage("plik wideo", ramka); else break; // czekamy przez okreslony czas int c = cvWaitKey(odstep_miedzy_klatkami); // jezeli nacisnieto klawisz 'k', konczymy wyswietlanie if (c == 'k') break; } // zwolnienie zasobow cvDestroyAllWindows(); cvReleaseCapture(&vid);W powyższych kodach pojawia się funkcja cvQueryFrame. Jak wspomniano, służy ona do pobierania ramek z CvCapture. Ten sam efekt można osiągnąć posługując się kolejno funkcjami cvGrabFrame i cvRetrieveFrame. Pierwsza z nich ściąga ramkę z kamery i pozostawia ją w stanie surowym w pamięci, a druga pobiera taką ramkę i zamienia ją na IplImage.
Ostatnią funkcjonalnością dzisiaj opisaną będzie zapis wideo. Zapisywać możemy kolejne obrazy IplImage. Nie musi być to zatem obraz z kamery czy przetworzony plik wideo. Przykład:
// pobranie zasobu kamery, parametr mowi o tym ktora kamere wybieramy // w przypadku gdy w systemie dostepna jest wiecej niz jedna CvCapture* vid = cvCreateCameraCapture(0); // tworzymy okno wyswietlajace obraz // jako parametr przekazujemy CV_WINDOW_AUTOSIZE, ktory utworzy okno o wielkości // odpowiadajacej wyswietlanemu obrazowi cvNamedWindow("plik wideo", CV_WINDOW_AUTOSIZE); // odczytanie pierwszej klatki - niezbedne do prawidlowego odczytania wlasciwosci pliku // przy uzyciu funkcji cvGetCaptureProperty cvQueryFrame(vid); // ustalamy wartosc fps double fps = 30; int odstep_miedzy_klatkami = 1000 / fps; // tworzymy strukture zapisujaca klatki do pliku // kolejno podajemy: sciezke do pliku, format, fps i rozmiar ramki (opcjonalnie czy obraz ma byc w kolorze) CvVideoWriter* vr = cvCreateVideoWriter("/home/lukasz/Pulpit/zapis.mpg",CV_FOURCC_DEFAULT,fps,cvSize(640,480)); while (true) { // pobranie kolejnej klatki IplImage* ramka = cvQueryFrame(vid); // jezeli nie jest pusta to wyswietlamy if (ramka != 0) { cvShowImage("plik wideo", ramka); // zapisujemy ramke do pliku cvWriteFrame(vr,ramka); } else break; // czekamy przez okreslony czas int c = cvWaitKey(odstep_miedzy_klatkami); // jezeli nacisnięto klawisz 'k', konczymy wyswietlanie if (c == 'k') break; } // zwolnienie zasobow cvDestroyAllWindows(); cvReleaseCapture(&vid); cvReleaseVideoWriter(&vr);
Jakieś wady? Niestety tak. Nie da się ukryć, że kamerki komputerowe mają zmienny (zależny np. od oświetlenia) współczynnik fps. W CvVideoWriter nie zmienimy tego po utowrzeniu, więc film może zachowywać się nieprzewidywalnie w trakcie nagrywania. Problem nie dotyczy oczywiście zapisu wcześniej przygotowanych statycznych obrazów. Jeżeli ktoś posiada lepszy pomysł na synchronizację obrazu z kamery z nagrywaniem to zapraszam do komentarzy ;-)
5 komentarzy:
Czekam niecierpliwie na dalsze części zmagań z openCV
Postaram się zwiększyć tempo postowania
Czy za pomocą openCV można zapisywać obraz z prędkością np. 5 klatek/min?
Cześć
Siedzę trochę w temacie kamer ale do systemów CCTV. Wydaje mi się, że prędkość wyświetlania obrazu zależy wyłącznie od przetworników z których zbudowana jest kamera. Dobre kamery powinny utrzymać stałą jakość obrazu.
czy zwolnienie zasobów nie powinno mieć miejsca w innej kolejności ?
tzn :
// zwolnienie zasobow
cvReleaseCapture(&vid);
cvDestroyAllWindows();
??
Prześlij komentarz