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