'공부합시다/영상처리'에 해당되는 글 3건

  1. 2009.07.21 VFW 영상 처리 함수
  2. 2009.07.15 비트맵 헤더 분석
  3. 2009.07.15 비트맵 파일의 구조
2009. 7. 21. 08:42

VFW 영상 처리 함수

비디오 캡쳐를 하기 위해서 먼저 vfw32.lib 를 프로젝트에서 포함 해주어야 하며 작성 소스 상단에 Vfw.h를

include 해주어야 한다.

 

비디오 캡쳐를 위한 작업 순서를 간단히 다음과 같다.

 

- 캡쳐 윈도우를 생성

- 윈도우와 캡쳐 드라이버를 연결

- 캡쳐된 비디오 프레임을 캡쳐 윈도우를 통해서 출력

캡쳐된 비디오 프레임을 캡쳐 윈도우에 보여주기 위해서는 한 프레임이 캡쳐 될 때마다 특정 함수를 호출하도록 한 다음에 호출된 함수에서 그 프레임을 화면에 출력한다.

이러한 작업을 수행하기 위해서는 VFW 라이브러리 중에서 다음과 같은 함수들을 사용해야 한다.

capGetDriverDescription()

CapCreateCaptureWindow()

capDriverConnect()

capPreviewRate()

capSetVideoFormat()

capDriverDisconnect()

capSetCallbackOnFrame()

 

 - 함수의 원형

 

HWND VFWAPI capCreateCaptureWindowW (
        LPCWSTR lpszWindowName,
        DWORD dwStyle,
        int x, int y, int nWidth, int nHeight,
        HWND hwndParent, int nID);

이 함수는 캡쳐 윈도우를 생성한다. name 에는 윈도우위 이름을 지정한다. style 윈도우위 스타일을 지정한다. (x,y)에는 캡쳐 윈도우의 좌측 상단의 좌표를 지정한다. width height에는 캡쳐 윈도우의 크기를 지정한다. hWnd에는 부모윈도우의 핸들값을 입력한다. id에는 윈도우의 식별 번호를 입력한다. 캡쳐 윈도우가 정상적으로 생성되면 캡쳐 윈도우의 핸들의 함수 결과값으로 반환되고 그렇지 않으면 NULL값이 반환된다.

 

 

BOOL VFWAPI capGetDriverDescriptionW (UINT wDriverIndex,
        LPWSTR lpszName, int cbName,
        LPWSTR lpszVer, int cbVer);

이 함수는 캡쳐 드라이버의 이름 및 버전 정보를 검색한다. 첫 번째 매개변수인 index는 검색하고자 하는 드라이버의 번호를 나타내는데, 0부터 9까지의 값을 가질 수 있다.

즉, 한 컴퓨터에서 9대의 캡쳐 장치가 사용될 수 있다고 가정하고 있다. 검색하고자 하는 번호의 드라이버가 존재하면 이 함수는 name에 드라이버의 이름을 저장하고 version에 드라이버 버전을 저장한 다음에 함수 결과값으로 TURE 값을 반환한다. 

 

capDriverConnect(hWnd, index);

이 함수는 아래 처럼 디파인 되어 있으며

#define capDriverConnect(hwnd, i)          ((BOOL)AVICapSM(hwnd, WM_CAP_DRIVER_CONNECT, (WPARAM)(i), 0L))

AVICapSM 역시 아래 처럼 디파인 되어 있다.( 윈도우 메시지인 WM_CAP_DRIVER_CONNECT 를 사용 하는듯 하다.)

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

이 함수는 캡쳐 윈도우를 캡쳐 드라이버에 연결한다. hWnd는 캡쳐 윈도우의 핸들을 나타내고 index는 캡쳐 드라이버의 번호를 나타낸다. 이 함수는 캡쳐 장치가 정상적으로 작동하여 연결이 성공되면 TURE 값을 반환하고 그렇지 않으면 FALSE 값을 반환한다.

 

 

capPreviewRate(hWnd, rate);

이 함수는 아래 처럼 디파인 되어 있으며

#define capPreviewRate(hwnd, wMS)   ((BOOL)AVICapSM(hwnd, WM_CAP_SET_PREVIEWRATE, (WPARAM)(wMS), 0))

AVICapSM 역시 아래 처럼 디파인 되어 있다.( 윈도우 메시지인 WM_CAP_SET_PREVIEWRATE를 사용 하는듯 하다.)

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

이 함수는 미리보기 (preview)모드에서의 프레임 재생 속도를 설정한다. 여기에서 미리보기란 카메라에서 입력된 비디오를 파일에 저장하는 것이 아니라 화면에 보여준다는 것을 의미한다. hWnd는 캡쳐 윈도우의 핸들 값으로 설정하고 rate는 밀리초(ms) 단 위의 시간으로 설정한다. 예를 들어, rate 값을 66으로 설정하면 0.066초마다 새로운 비디오 프레임을 캡쳐해서 디스플레이 하게 도니다. 이와 같은 속도로 재생을 하면 1초에 15개의 비디오 프레임이 디스플레이된다.

 

capSetVideoFormat(hWnd, videoFormat, videoFormat_size);

#define capSetVideoFormat(hwnd,s,wSize)          ((BOOL)AVICapSM(hwnd, WM_CAP_SET_VIDEOFORMAT, (WPARAM)(wSize), (LPARAM)(LPVOID)(s)))

AVICapSM 역시 아래 처럼 디파인 되어 있다.( 윈도우 메시지인 WM_CAP_SET_VIDEOFORMAT를 사용 하는듯 하다.)

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

이 함수는 캡쳐된 비디오 데이터 형식을 설정한다. 사용자가 원하는 비디오 데이터형식이 캡쳐 장치에서 지원이 되면 이 함수는 TRUE 값을 반환하고 그렇지 않으면 FALSE 값을 반환하므로 반드시 이 함수의 결과값이 TRUE 인지 검사한 다음에 다음단계로 넘어가야 한다.

hWnd는 캡쳐 윈도우의 핸들 값으로 설정한다. videoFormat은 설정하고자 하는 비디오 데이터 형식을 나타내는데, 비디오 데이터의 각 프레임에 대한 비트맵 형식을 BITMAPINFO 구조로 기술한다.

 

BITMAPINFO 구조는 다음과 같다.

typedef struct tagBITMAPINFO{

BITMAPINFOHEADER bmiHeader;

RGBQUAD bmiColrs[1];

} BITMAPINFO;  

BITMAPINFO는 BITMAPINFOHEADER와 RGBQUAD로 구성되는데, 여기에서는 다음과 같이 정의되는 BITMAPINFOHEADER 구조체의 값만 사용하면 된다.


pBmiInfo->bmiHeader.biSize = 40;  //BITMAPINFOHEADER 구조체의 크기

pBmiInfo->bmiHeader.biHeight = 480; //영상의 가로크기

pBmiInfo->bmiHeader.biWidth = 640;

//영상의 세로크기(양수:좌측 하단이 원점   음수:좌측 상단이 원점)

pBmiInfo->bmiHeader.biPlanes = 1; //목표 장치의 플레인 수(1로 설정해야함)

pBmiInfo->bmiHeader.biBitCount = (short) 24; //각 픽셀의 비트수

pBmiInfo->bmiHeader.biCompression = 0; //압축 방법(bi_rgb 또는 0:무압축 비트맵)

pBmiInfo->bmiHeader.biSizeImage =0; //비트맵 영상 크기(무압축인 경우 0으로 설정)

pBmiInfo->bmiHeader.biClrImportant = 0; // 비트맵 디스플레이에 사용되는 컬러수

pBmiInfo->bmiHeader.biClrUsed = 0; // 사용된 컬러의 수

pBmiInfo->bmiHeader.biXPelsPerMeter = 10000; //수평 해상도 (미터당 픽셀수)

pBmiInfo->bmiHeader.biYPelsPerMeter = 10000; //수직 해상도 (미터당 픽셀 수)

}BITMAPINFOHEADER;

비디오 캡쳐를 위해서는 다음과 같이 BITMAPINFOHEADER 구조체에서 biSize,biWidth, biHeight, biPlanes, biBitCount 값을 설정하고 나머지 값을은 0으로 설정하면된다.

BITMAPINFO bmi;

memset(&bmi.bmiHeader, 0, sizeof(bmiHeader));

pBmiInfo->bmiHeader.biSize = sizeof(bmi.bmiHeader);

pBmiInfo->bmiHeader.biWidth = 640;//영상의 세로크기(양수:좌측 하단이 원점

pBmiInfo->bmiHeader.biHeight = 480;//영상의 가로크기

pBmiInfo->bmiHeader.biPlanes = 1;//목표 장치의 플레인 수(1로 설정해야함)

pBmiInfo->bmiHeader.biBitCount =  24;//각 픽셀의 비트수

 

capDriverDisconnect(hWnd);

#define capDriverDisconnect(hwnd)       ((BOOL)AVICapSM(hwnd, WM_CAP_DRIVER_DISCONNECT, (WPARAM)0, 0L))

AVICapSM 역시 아래 처럼 디파인 되어 있다.( 윈도우 메시지인 WM_CAP_DRIVER_DISCONNECT를 사용 하는듯 하다.)

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

이 함수는 carDriverConnect() 함수에 의하여 연결한 캡쳐 윈도우와 캡쳐 장치를 분리하는 함수이다. hWnd에는 분리하고자 하는 캡쳐 윈도우의 핸들 값을 설정한다.

 

BOOL capSetCallbackOnFrame(hWnd, func);

#define capSetCallbackOnFrame(hwnd, fpProc)        ((BOOL)AVICapSM(hwnd, WM_CAP_SET_CALLBACK_FRAME, 0, (LPARAM)(LPVOID)(fpProc)))

AVICapSM 역시 아래 처럼 디파인 되어 있다.( 윈도우 메시지인 WM_CAP_SET_CALLBACK_FRAME를 사용 하는듯 하다.)

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

VFW 라이브러리에서는 캡쳐된 비디오 프레임을 화면에 보여주는 작업을 callback함수를 사용해서 처리하도록 하고 있다. capSetCallbackOnFrame()함수는 캡쳐 장치로부터 비디오 프레임이 캡쳐되었을때에 이를 화면에 보여주기 위해서 호출되는 callback 함수를 설정한다. hWnd는 캡쳐 윈도우의 핸들 값으로 설정하고 func는 호출될 함수 이름으로 설정한다.  

 

 

BOOL capOverlay(hWnd, f);
#define capOverlay(hwnd, f)          ((BOOL)AVICapSM(hwnd, WM_CAP_SET_OVERLAY, (WPARAM)(BOOL)(f), 0L))

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

이 함수는 비디오 오버레이를 사용 할것인지 아닌지를 설정한다. 설정 성공시 TRUE, 그렇지 않을경우 FALSE를 반환.
매개변수는 순서대로 윈도우 핸들, 설정시-true 미설정시 -false
비디오 오버레이를 사용하면 CPU자원이 요구 되지 않아 효과적이라고 한다. 
 
BOOL capPreview(hWnd, f);
#define capPreview(hwnd, f)       ((BOOL)AVICapSM(hwnd, WM_CAP_SET_PREVIEW, (WPARAM)(BOOL)(f), 0L))

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

이 함수는 미리보기 모드를 동작 시킬 것인지 아닌지를 설정한다. 설정을 하게 되면 영상 프레임이 시스템의 메모리로 전달되어 GDI함수를 사용하여 캠처 윈도우에 영상을 출력하게 된다.
매개 변수는 순서대로 윈도우 핸들, 설정시 -true, 미설정시 -false 

'공부합시다 > 영상처리' 카테고리의 다른 글

비트맵 헤더 분석  (0) 2009.07.15
비트맵 파일의 구조  (0) 2009.07.15
2009. 7. 15. 13:34

비트맵 헤더 분석

이번엔 실제 BMP파일을 헥스뷰어로 열어보고 헤더의 정보를 살펴보도록 하겠다.


위의 BMP 파일을 WinHex 같은 헥스뷰어로 열어보면, 다음과 같은 화면을 볼 수 있다.


BMP 헤더 정보
1. 0x0 ~ 0x1: 가장 처음의 두 바이트는 매직넘버이다. B와 M에 해당하는 ASCII값인 42, 4D가 보인다.

2. 0x2 ~ 0x5: 그 다음 부터 4바이트는 파일의 크기이다. 다만, 리틀 인디안으로 저장되어 있으므로 0x64356가 된다. 실제로 저 그림 파일을 다운받아 저장해보면 410,454 바이트인것을 알 수 있는데 이를 16진수로 변환하면 0x64356이 된다.

3. 그 다음 2바이트와 그 다음 2바이트는 응용프로그램에 따라 달라지는데 이는 다음 기회에 알아보도록 하자.

4. 0xA ~ 0xD : 픽셀 데이터의 시작 위치 이다. 헤더의 크기 14바이트와 비트맵 정보 40바이트(윈도우v3 비트맵일 경우. 대부분 이경우다.), 총 54바이트 다음인 0x36번지 부터 픽셀데이터가 기록되어 있다.

비트맵 정보
1. 0xE ~ 0x11 : 헤더의 크기. 0x28 = 40 이므로 헤더의 크기는 40바이트이다. 즉, 윈도우 v3 비트맵이란 이야기.

2. 0x12 ~ 0x15 : 비트맵 가로크기. 비트맵은 그림의 가로 길이가 4의 배수가 아닌 경우 더미 데이터가 들어가게 된다. 0x1E0 = 480 이므로, 이 비트맵의 가로 크기는 480이다.

3. 0x16 ~ 0x19 : 비트맵 세로 크기.

4. 0x1A ~ 0x1B : 사용하는 색 판(color plane)의 수. 1로 설정해야 한다.

5. 0x1C ~ 0x1D :
한 화소에 들어가는 비트 수이며 그림의 색 깊이를 뜻한다. 보통 값은 1, 4, 8, 16, 24, 32이다. 이 파일의 경우는 0x18 = 24비트이다.

6. 0x1E ~ 0x21 :
압축 방식. 비트맵도 압축 방식이 있다. 하지만 잘 사용하지 않는다. 따라서 값은 0.

7. 0x22 ~ 0x25 :
그림 크기. 압축되지 않은 비트맵 데이터의 크기이며, 파일 크기와 혼동하지 말 것. 즉, 헤더를 제외한 크기. 이 파일의 경우에는 0x64320인데 파일크기는 0x64356이므로, 0x36바이트 즉, 54바이트의 헤더를 제외한 만큼 차이가 난다.

8. 0x26 ~ 0x29 : 그림의 가로 해상도. (미터 당 화소, signed integer)

9. 0x2A ~ 0x2D :
그림의 세로 해상도. (미터 당 화소, signed integer)

10. 0x2E ~ 0x31 :
색 팔레트의 색 수, 또는 0에서 기본값 2n.

11. 0x32 ~ 0x35 :
중요한 색의 수. 모든 색이 중요할 경우 0. 일반적으로 무시.

픽셀 데이터

0x36 ~ : 한 픽셀을 표현하기 위해 R, G, B 3바이트가 필요하므로, 3바이트씩 한픽셀을 표현한다. 다만 리틀 인디언이므로 BGR의 순으로 저장되어 있다. 또한, BMP파일은 그림의 상하를 반대로 저장하므로 첫 픽셀의 정보는 그림의 가장 아래줄 첫번째 픽셀이 된다.

'공부합시다 > 영상처리' 카테고리의 다른 글

VFW 영상 처리 함수  (0) 2009.07.21
비트맵 파일의 구조  (0) 2009.07.15
2009. 7. 15. 12:23

비트맵 파일의 구조

비트맵(BMP) 파일은 가장 간단한 구조의 이미지 파일 중 하나이다. 기본적으로 1, 4, 8, 16, 24, 32 비트를 지원하지만 16과 32비트는 잘 사용하지 않는다. bmp파일은 구조가 간단한 만큼 용량이 매우 큰 파일이다. 그렇기 때문에 기본적인 압축형식을 지원하지만 효율이 그다지 좋지 않아 압축을 사용하는 경우는 드물다.

BMP 파일 포맷은 단순하고 윈도와 같은 여러 곳에서 널리 쓰일뿐 아니라 상대적으로 특허에서 자유로우므로, 수많은 운영 체제가 제공하는 그림 처리 프로그램이 읽고 쓸 수 있는 매우 일반적인 포맷으로 자리잡았다.

bmp파일도 여러가지 방식이 있기는 하지만 대부분이 사장되고, 현재 남은 형식은 windows version3를 가장 많이 사용하고 있다. 물론 OS/2같은 운영체제에서는 다른 형식을 사용하기도 한다.

BMP 파일의 구조

일반적으로 쓰이는 BMP는 다음의 데이터 블록을 담고 있다.

 BMP 헤더
 BMP 파일에 대한 일반 정보를 담고 있다.
 비트맵 정보(DIB 헤더)
 비트맵 그림에 대한 자세한 정보를 담고 있다.
 색 팔레트
 인덱스 컬러 비트맵에 쓰이는 색의 정의를 담고 있다.
 비트맵 데이터
 화소 대 화소 단위의 실제 그림을 담고 있다.

1. BMP 파일 헤더

오프셋#

크기

목적

0

2

BMP 파일을 식별하는 데 쓰이는 매직넘버:0x42 0x4D (B와 M에 대한 ASCII 코드값)

2

4

BMP 파일 크기(바이트 단위)

6

2

그림을 만드는 데 쓰인 응용 프로그램에 따라 달라진다.

8

2

그림을 만드는 데 쓰인 응용 프로그램에 따라 달라진다.

10

4

오프셋. 픽셀 데이터의 시작 주소(바이트 단위)


2. 비트맵 정보(DIB 헤더)

기본적으로 쓰이는 비트맵 정보는 다음과 같다.

크기

헤더

식별자

GDI지원

40

윈도우 V3

BITMAPINFOHEADER

윈도우 3.0 이후의 모든 윈도우 버전

12

OS/2 V1

BITMAPCOREHEADER

OS/2 및 윈도 3.0 이후의 모든 윈도 버전

64

OS/2 V2

 

 

108

윈도우 V4

BITMAPV4HEADER

윈도우 95/NT4 이후의 모든 윈도우 버전

124

윈도우 V5

BITMAPV5HEADER

윈도우 98/2000 이상


 호환성을 이유로 대부분의 응용 프로그램은 파일을 저장할 때 오래된 DIB 헤더를 사용한다. OS/2가 물러나자, 이제 일반적으로 쓰이는 포맷은 V3 헤더가 되었다. 더 자세한 것은 아래의 표를 참조하자.

오프셋 #

크기

목적

14

4

이 헤더의 크기 (40 바이트)

18

4

비트맵 가로 (단위는 화소, signed integer).

22

4

비트맵 세로 (단위는 화소, signed integer).

26

2

사용하는 색 판(color plane)의 수. 1로 설정해야 한다.

28

2

한 화소에 들어가는 비트 수이며 그림의 색 깊이를 뜻한다. 보통 값은 1, 4, 8, 16, 24, 32이다.

30

4

압축 방식. 가능한 값에 대한 목록은 다음 표를 참조하라.

34

4

그림 크기. 압축되지 않은 비트맵 데이터의 크기(아래 참조)이며, 파일 크기와 혼동하지 말 것.

38

4

그림의 가로 해상도. (미터 당 화소, signed integer)

42

4

그림의 세로 해상도. (미터 당 화소, signed integer)

46

4

색 팔레트의 색 수, 또는 0에서 기본값 2n.

50

4

중요한 색의 수. 모든 색이 중요할 경우 0. 일반적으로 무시.




'공부합시다 > 영상처리' 카테고리의 다른 글

VFW 영상 처리 함수  (0) 2009.07.21
비트맵 헤더 분석  (0) 2009.07.15