작년 8월쯤 (회사 입사때쯤이라 기억하고 있음)에 마소 잡지를 뒤적이던 중에 OpenCV라는 오픈소스의 Computer Vision 라이브러리를 알게 되었다. 이게 “물건”이구나라는 것을 느꼈고, 다운로드 받아 대충이라도 살펴 보았지만, 잠시 시간의 흐름과 함께 내 관심밖으로 밀려나갔다. 그러던중에… 요즘 오픈소스인 Ogre3D도 분석해보고 하던차에, OpenCV가 생각났다. GIS에서 위성영상이나 항공영상으로부터 데이터를 추출하는 등, 이미지 처리 분야는 매우 중요하고 앞으로 더욱 중요해질 것이다.
먼저 OpenCV가 뭐에 쓰는 물건인지는 알아서들 알아내시고…(뜨헉~ -_-;) 이번엔 OpenCV의 기능중 빙산의 일각인 화상카메라로부터 영상을 취득한 후에, 취득한 영상에서 움직이는 물체를 검출해보는 기능을 작성해 보았다. 매우 다양하고 효율적인 방법이 많이 있을지 모르겠지만, 당장 생각나는 방법은 현재 프레임 영상과 바로 이전 프레임 영상에 대한 같은 위치의 화소값을 비교해서 다르면 움직이는 물체에 대한 화소일 것이라는 아이디어로 접근해 보았다.
하지만 동일한 위치의 화소값이 두 프레임 이미지가 정확히 일치라는 비교는 무리가 있었다. 화상카메라에서 취득하는 영상은, 비록 움직이는 물체가 없을지라도 미세하게나마 연속된 프레임일지라도 다르게 취득되었다. 그래서 동일한 위치의 화소값의 차이가 어느 정도의 차이가 날때 움직이는 물체다.. 라는 기준으로 접근을 해 보았다. 결과는 처음치곤 만족할 만했다.
아래는 프레임 영상을 받아서 실제 움직이는 물체를 검출해주는 소스코드이다.
void OnFrame(IplImage* image) {
HDC hDC = GetDC(m_hWnd);
SetDIBitsToDevice(hDC, 0, 0, image->width, image->height, 0, 0, 0,
image->height, image->imageData, (BITMAPINFO *)&m_bmpInfo,
DIB_RGB_COLORS);
SetDIBitsToDevice(hDC, 330, 0, image->width, image->height, 0, 0, 0,
image->height, image->imageData, (BITMAPINFO *)&m_bmpInfo,
DIB_RGB_COLORS);
IplImage* gray=cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
cvCvtColor(image, gray, CV_BGR2GRAY);
if(bHasOldImage) {
HRGN hRgn = CreateRectRgn(330, 0, 330+320, 240);
SelectClipRgn(hDC, hRgn);
float CriticalValue = 15.0f;
for(int x=0; xwidth; x+=6) {
for(int y=0; yheight; y+=6) {
uchar c1 = ((uchar*)(gray->imageData +
gray->widthStep*y))[x];
uchar c2 = ((uchar*)(m_oldGrayImage->imageData +
m_oldGrayImage->widthStep*y))[x];
if(fabs(float((float)c1-(float)c2))>CriticalValue)
{
int X = 330+x;
int Y = image->height-1-y;
Rectangle(hDC, X-3, Y-3, X+3, Y+3);
}
}
}
DeleteObject(hRgn);
}
m_oldGrayImage=cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
cvCvtColor(image, m_oldGrayImage, CV_BGR2GRAY );
bHasOldImage = true;
ReleaseDC(m_hWnd, hDC);
}
대략 설명해 본다면, 우선 OnFrame 함수는 OpenCV에서 화상카메라로부터 영상이 들어올때 실행되는 Callback 함수이다. 영상은 24비트로 들어오는데 속도와 계산을 간단하게 하기 위해서 8비트인 Gray로 변환하기 위해 cvGray를 사용하였다. 연속되는 프레임 영상의 같은 위치의 화소값을 비교하여 움직이는 물체에 대한 화소인지의 비교한 차이값으로 15를 사용하였음을 알 수 있다. 차이값이 15이상인 화소의 위치에 White Box를 그려주었다.