background image

Architektura Systemów Komputerowych, Wydział Informatyki, ZUT  

Opracował: Mariusz Kapruziak (

mkapruziak@wi.ps.pl

)                               wersja: 2009-11-11    1

Laboratorium: MS Windows – obsługa kamery 

 

 

Krok 1. 

Uruchamiamy Visual Studio C++. Otwieramy nowy projekt (menu-File-

New-Project). Konfigurujemy tak jak na rysunku poniżej. Projekt umieszczamy w 
katalogu  C:\users\inazwisko gdzie inazwisko to pierwsza litera swojego imienia i 
nazwisko (bez spacji).  

 

 

 

Rys. 1. Okno zakładania nowego projektu

 

 

Krok 2. 

Konfigurujemy wzorzec projektu tak jak na rysunku poniżej (typu Single 

Document).  

 

 
 
 
 
 
 
 
 
 

Rys. 2. Okno konfiguracji projektu

 

background image

Architektura Systemów Komputerowych, Wydział Informatyki, ZUT  

Opracował: Mariusz Kapruziak (

mkapruziak@wi.ps.pl

)                               wersja: 2009-11-11    2

Krok 3. 

Otwieramy plik „KameraView.h” i wprowadzamy modyfikacje: 

1)  dołączamy plik „Vfw.h” (rys.3) 
2)  dodajemy pole HWND m_wndKamera (rys.3) 
3)  Dodajemy symbol ID_CAMWND (rys.4) 
 

 

 

 

Rys. 3. Modyfikacje w pliku KameraView.h

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

1

2

Rys. 4. Dodawanie symbolu ID_CAMWND 

background image

Architektura Systemów Komputerowych, Wydział Informatyki, ZUT  

Opracował: Mariusz Kapruziak (

mkapruziak@wi.ps.pl

)                               wersja: 2009-11-11    3

Krok 4. 

Do klasy CKameraView dodajemy metodę OnInitialUpdate (rys.5). 

Wpisujemy kod do utworzonej metody (rys.6). Następnie uruchamiamy program. 
Powinniśmy otrzymać komunikat błędu taki jak na rys.7.  
 

 

 
 

 
komentarz: 
Funkcja  capCreateCaptureWindow tworzy okno przechwytywania strumienia wideo. 
Wykorzystując technologię Vfw (Video for Windows) trzeba takie okno utworzyć, nawet jeśli nie 
chcemy aby było widoczne. Zaleca się spojrzenie do dokumentacji MSDN w celu przeanalizowania 
argumentów przekazywanych do funkcji. Ciekawszą obserwacją może być sposób otrzymania 
uchwytu do „naszego” okna (CKameraView), które ma się stać oknem nadrzędnym względem 
tworzonego. Wykorzystana jest do tego metoda GetSafeHwnd. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

void

 CKameraView::OnInitialUpdate(){ 

    CView::OnInitialUpdate(); 

 

    

// TODO: Add your specialized code here 

 

    HWND hwndParent = 

this

->GetSafeHwnd(); 

    m_wndKamera = capCreateCaptureWindow( L

"Nazwa"

     WS_CHILD 

WS_VISIBLE, 

 

 

  

 

 

 

10, 10, 640, 480,         

     hwndParent, 

ID_CAMWND 

); 

 

 

 

}

//--------------------------------------------------- 

Rys. 5. Dodawanie metody 

OnInitialUpdate 

Rys. 6.  Kod w OnInitialUpdate() 

Rys. 7.  Spodziewany komunikat błędów 

background image

Architektura Systemów Komputerowych, Wydział Informatyki, ZUT  

Opracował: Mariusz Kapruziak (

mkapruziak@wi.ps.pl

)                               wersja: 2009-11-11    4

Krok 5. 

Dodajemy do linkera powiązanie z biblioteką vfw32.lib (rys.8). Następnie 

uruchamiamy program ponownie.  
 
 

 
 
 
 
 
 
 
 
 

Rys. 8. Dodanie powiązania do vfw32.lib

 

 
komentarz: 
Tym razem kompilacja i łączenie powinno przejść pomyślnie. W wyniku powinniśmy otrzymać 
okno z czarnym kwadratem w środku o rozmiarach 640 na 480. W tym kwadracie w dalszych 
etapach będzie pokazywany obraz z kamery po jego przetworzeniu wykonanym przez nas. 

 
Krok 6. 

Enumeracja urządzeń

 

komentarz: 
Wykorzystując Vfw można obsługiwać do 10 urządzeń wideo. Każde dostaje swój numer. Które 
urządzenie jest gotowe do obsługi i które ma jaki numer można określić wykorzystując funkcje 
capGetDriverDescription,  capDriverGetName oraz capDriverGetCaps. Do 
połączenia się ze sterownikiem służy funkcja capDriverConnect a do rozłączenia 
capDriverDisconnect.

  

 

Zadanie: 
Wypisać listę wszystkich urządzeń ich statusu oraz stanu ich gotowości: 

1)  Dodać tablicę łańcuchów (CString) do klasy CKameraView (rys.9). 
2)  Dodać kod do enumeracji w OnInitialUpdate (rys.10). 
3)  Przeanalizować dodany kod, w sytuacji jakby coś nie było wystarczająco jasne 

KONIECZNIE PYTAĆ (ważne aby rozumieć) 

4)  Dodać kod do OnDraw wypisujący listę urządzeń na ekranie (rys.11). 

 
 
 
 
 
 
 
 

background image

Architektura Systemów Komputerowych, Wydział Informatyki, ZUT  

Opracował: Mariusz Kapruziak (

mkapruziak@wi.ps.pl

)                               wersja: 2009-11-11    5

5)   

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Rys. 9. Modyfikacje w KameraView.h – dodanie tablic łańcuchów z opisem urządzeń

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
 
 
 

 

 

Rys. 10. Kod w metodzie OnInitialUpdate

 

void

 CKameraView::OnInitialUpdate(){ 

 CView::OnInitialUpdate(); 

 

 

HWND hwndParent = 

this

->GetSafeHwnd(); 

 

m_wndKamera = capCreateCaptureWindow( L

"Nazwa"

, WS_CHILD | WS_VISIBLE,  

 

 

 

 

 

 

10, 10, 640, 480, hwndParent, ID_CAMWND ); 

 

 

 

for

int

 i =0; i<10; i++ ){ 

 

 

 

bool

 res = capDriverConnect( m_wndKamera, i ); 

 

  m_bIsDrivers[i] 

res; 

  m_strDriversParam[i] 

L

"     "

 

 

if

( res ){ 

 

 

 

 

char

 mstring[80]; 

 

 

 

capDriverGetName( m_wndKamera, mstring, 80 ); 

 

 

 

 

   CAPDRIVERCAPS 

drvCaps; 

 

   capDriverGetCaps( 

m_wndKamera, 

&drvCaps, 

sizeof

( drvCaps ) ); 

   m_strDriversEnum[i].Format( 

L

"%d.  %s"

, i, mstring ); 

 

 

 

 

 

 

 

if

( drvCaps.fHasDlgVideoSource ){ 

    m_strDriversParam[i] 

+= 

L

"SourceDLG; "

   }; 

 

 

 

 

if

( drvCaps.fHasDlgVideoFormat ){ 

    m_strDriversParam[i] 

+= 

L

"FormatDLG; "

   }; 

 

 

 

 

if

( drvCaps.fCaptureInitialized ){ 

    m_strDriversParam[i] 

+= 

L

"INIT; "

   }; 

 

 

 

}

else

   m_strDriversEnum[i].Format( 

L

"%d.  ----------"

, i ); 

  }; 

 

  capDriverDisconnect( 

m_wndKamera 

); 

 

 }; 

 

}

//----------------------------------------------------------------------------- 

class

 CKameraView : 

public

 CView 

protected

// create from serialization only 

 CKameraView(); 

 DECLARE_DYNCREATE(CKameraView) 

 

protected

:  

 HWND 

m_wndKamera; 

 

 CString 

m_strDriversEnum[10]; 

 CString 

m_strDriversParam[10]; 

 

bool

 m_bIsDrivers[10]; 

 

 

 

background image

Architektura Systemów Komputerowych, Wydział Informatyki, ZUT  

Opracował: Mariusz Kapruziak (

mkapruziak@wi.ps.pl

)                               wersja: 2009-11-11    6

 
 
 
 
 
 
 
 
 

Rys. 11. Kod w metodzie OnDraw – wyświetlanie tekstów

 

 

komentarz: 
Pomysł algorytmu jest dość prosty. Na etapie inicjalizacji w pętli pytane jest wszystkie 10 
możliwych urządzeń (pętla for) o parametry. W tym celu należy połączyć się ze sterownikiem 
urządzenia (capDriverConnect) i jeśli połączenie się udało (sterownik właściwy) to zapytać go 
o nazwę 

(capDriverGetName) oraz zapewniane przez sterownik możliwości 

(capDriverGetCaps,  końcówka -Caps od Capabilities). Procedura wypełnia właściwe 
łańcuchy (odpowiednio m_strDriversEnum 

do numeru oraz nazwy oraz 

m_strDriversParam do zapewnianych możliwości) oraz wypełnia informacje, czy sterownik 
był dostępny(m_bIsDrivers). Obie tablice łańcuchów jak również informacja o dostępności 
sterownika wykorzysytwana jest w procedurze obsługi komunikatu WM_PAINT (rysowanie 
ekranu, metoda OnDraw w tym przypadku).  

 
Krok 7. 

Połączenie ze sterownikiem kamery, ustawienie parametrów kamery i 

pobieranie ramki obrazu.  

 
Zadanie: 
Pokazać w oknie właściwy obraz z kamery i pobierać nową ramkę na żądanie ręcznie oraz 
automatycznie w procedurze obsługi WM_TIMER: 

1)  Połączyć się ze sterownikiem oraz uruchomić okno ustalania parametrów 

(capDlgVideoFormat) (rys.12). 

2)  Uruchomić aplikację, powinno na starcie uruchomić się okno dialogowe z możliwością 

ustawiania parametrów kamery. Ustawić rozdzielczość 640x480 oraz kompresje na 
RGB24 (rys.13). 

3)  Dodać do menu aplikacji nowe wpisy (rys.14). 
4)  Dodać metodę na obsługę zdarzenia wybrania komendy „Pobierz ramke” z menu 

(rys.15). 

5)  Dodać obsługę komunikatów OnKameraFilmTimerStart oraz OnKameraFilmTimerStop 

analogicznie do punktu 4. 

6)  Dodać metodę OnTimer obsługujące komunikat WM_TIMER (rys.17). W celu obsługi 

komunikatu od Timera należy dodać symbol ID_TIMER, podobnie jak to robione było z 
symbolem ID_CAMWND (rys.4). 

7)  Wypisać kod do nowo utworzonych metod zgodnie z rys.18. 

 
 

 
 

void

 CKameraView::OnDraw(CDC* pDC){ 

 

 

int

 y = 20; 

 

for

int

 i =0; i<10; i++ ){ 

 

 

pDC->TextOut( 700, y, m_strDriversEnum[i] ); y += 20; 

 

 

if

( m_bIsDrivers[i] ){ 

 

 

 

pDC->TextOut( 700, y, m_strDriversParam[i] ); 

   y 

+= 

20; 

  }; 

 }; 

 

}

//----------------------------------------------------------------------------- 

 

background image

Architektura Systemów Komputerowych, Wydział Informatyki, ZUT  

Opracował: Mariusz Kapruziak (

mkapruziak@wi.ps.pl

)                               wersja: 2009-11-11    7

 

 

 

 
 
 
 
 

Rys. 12. Kod w metodzie OnDraw – wyświetlanie tekstów

 

 

 

 

Rys. 13. Przykładowe okno dialogowe ustawiania parametrów. 

 

 

 
 
 
 

void

 CKameraView::OnInitialUpdate(){ 

 … 

 

 

bool

 res = capDriverConnect( m_wndKamera, 0 ); 

 

capDlgVideoFormat( m_wndKamera ); 

 

}

//----------------------------------------------------------------------------- 

void

 CKameraView::OnKameraPobierz(){ 

 capGrabFrame( 

m_wndKamera, 

true

 ); 

}

//---------------------------------------- 

 

Rys. 15.  Dodanie metody 

obsługi komunikatu 

ID KAMERA POBIERZ 

Rys. 16.  Kod OnKameraPobierz. 

Rys. 14. Nowe wpisy w MENU.

 

background image

Architektura Systemów Komputerowych, Wydział Informatyki, ZUT  

Opracował: Mariusz Kapruziak (

mkapruziak@wi.ps.pl

)                               wersja: 2009-11-11    8

 

 
 
 
 

Krok 8. 

Modyfikacje na obrazie – odwracanie obrazu.  

 
Zadanie: 
Pokazać w oknie zanegowany obraz z kamery (tam gdzie był kolor biały ma być czarny itd.): 

1)  Dodać funkcję cbFunct. Ma znaczenie w którym miejscu w pliku CKameraView.cpp 

umieścimy tą funkcję. Powinna być umieszczona przed odwołaniem się do niej, czyli 
przed metodą OnInitialUpdate. Proponuje się umieszczenie jej kodu bezpośrednio za 
konstruktorem klasy.  

2)  Zmodyfikować metodę  OnInitialUpdate  dodając na końcu  wywołanie funkcji 

capSetCallbackOnFrame (rys.20). 

 
 
 

 
 
 
 
 
 
 
 
 
 
 
 

//------------------------------------------------ 

void

 CKameraView::OnKameraFilmTimerStart(){ 

 

SetTimer( ID_TIMER, 50, NULL ); 

}

//----------------------------------------------- 

 

//------------------------------------------------ 

void

 CKameraView::OnKameraFilmTimerStop(){ 

 

KillTimer( ID_TIMER ); 

}

//----------------------------------------------- 

 

//------------------------------------------------

void

 CKameraView::OnTimer(UINT_PTR nIDEvent){ 

 capGrabFrame( 

m_wndKamera, 

true

 ); 

 CView::OnTimer(nIDEvent); 

}

//----------------------------------------------- 

//------------------------------------------------------------------------------ 

LRESULT CALLBACK cbFunct(HWND hWnd, LPVIDEOHDR lpVHdr){ 

 

 

long

 size = lpVHdr->dwBufferLength; 

 

for

int

 x=0; x<640; x++ ) 

 

  

for

int

 y = 0; y<480; y++ ){ 

 

 

int

 i0 = x*3 + y * 3 * 640; 

 

 

lpVHdr->lpData[i0] = 255 - lpVHdr->lpData[i0];   

// BLUE 

 

 

lpVHdr->lpData[i0+1] = 255 - lpVHdr->lpData[i0+1]; 

// GREEN 

 

 

lpVHdr->lpData[i0+2] = 255 - lpVHdr->lpData[i0+2]; 

// RED 

 }; 

 

 

return

 (LRESULT) TRUE ;  

}

//----------------------------------------------------------------------------- 

void

 CKameraView::OnInitialUpdate(){ 

 

 … 

 

 

capSetCallbackOnFrame( m_wndKamera, cbFunct ); 

 

}

//----------------------------------------------------------------------------- 

Rys. 17.  Dodanie komunikatu  

OnTimer. 

Rys. 18.  Kod metod OnKameraFilmTimerStart, 

OnKameraFilmTimerStop oraz OnTimer 

background image

Architektura Systemów Komputerowych, Wydział Informatyki, ZUT  

Opracował: Mariusz Kapruziak (

mkapruziak@wi.ps.pl

)                               wersja: 2009-11-11    9

komentarz: 
Jest to typowe wykorzystanie mechanizmu CallBack. Przypominam w skrócie, że polega on na 
tym,  że do urządzenia przekazujemy adres funkcji którą chcemy aby on wykonał na skutek 
wybranego zdarzenia. Alternatywą do tego mechanizmu jest na przykład mechanizm 
wykorzystujący pętle komunikatów, na przykład ten znany z systemu MS Windows.  

 

W tym konkretnym przypadku zdarzeniem jest odebranie nowej ramki obrazu z kamery. Gdy nowa 
ramka nadejdzie sterownik urządzenia po jej sformatowaniu wywoła funkcję cbFunct. Pytanie do 
zastanowienia brzmi, jakie mogą być potencjalne wady wykorzystania mechanizmu CallBack, tak 
że nie jest on dominującym mechanizmem. 

 

 
Krok 9. 

(praca samodzielna) (1) Rysować tylko składową zieloną, (2) rysować 

obraz w odcieniach szarości (współczynniki uśredniania R:0.2125, G:0.7154, 
B:0.0721) (3) rysować obraz w odcieniach szarości ze współczynnikami uśredniania 
1/3 i porównać z pp.2, (3) Wykonać progowanie (thresholding) dla progu równego 50 
i eksperymentować z innymi wartościami progu.  

 
Krok 10. 

(praca samodzielna) Rysowanie na obrazie – funkcja rysująca zielony 

kwadrat pomiędzy zadanymi współrzędnymi (x

0

, y

0

) oraz (x

k

, y

k

).  

 

Krok 11. 

(praca samodzielna) Znajdowanie współrzędnej punktu ze wskaźnika 

laserowego (najbardziej czerwonego punktu na obrazie) i oznaczanie jej (śledzenie 
obiektu). Wypisać pod obrazem współrzędne tego obiektu.  
 

Krok 12. 

(praca samodzielna) Konkurs na najlepszy projekt na roku dotyczący 

rozpoznawania obrazów z kamery. Najlepszy projekt będzie nagrodzony oceną 
bardzo dobrą z całości kursu (laboratorium oraz wykładu).  

 
Linki do ciekawych pomysłów tego typu aplikacji (proszę nie ograniczać pomysłów do tego typu 
aplikacji, czym ciekawszy pomysł tym lepiej): 

http://www.youtube.com/watch?v=fGFypLpxD7M&feature=related

 

http://www.youtube.com/watch?v=ml4_MIM52g0&feature=related

 

http://www.youtube.com/watch?v=YBorbRaFrn8

 

http://www.youtube.com/watch?v=i_bZNVmhJ2o

 

http://www.youtube.com/watch?v=exbGdHpFiW0