OpenCV 초보를 위한 강좌 1편

OpenCV 는 인텔에서 만든 강력한 영상처리 라이브러리입니다.

강력한 기능과 성능에도 불구하고 3D 의 오픈소스라이브러리인 OpenGL 처럼 알려지지도 않고,

활발하게 개발되지도 않고, 자주 쓰이지도 않아 안타까운 심정입니다.

더욱이 국내에는 아직 활성화된 커뮤니티가 없어 자료를 구하기도 어려운 실정입니다.

그리하여 본인이 자료를 수집하고 공부하는 과정에서부딪친 문제점들의 해결방법들과

습득한 지식들을 강좌를 통해 풀어나가 보려고 합니다.

강좌는 다음과 같은 목차로 진행될 예정이며예제 위주와 간결한 문체를 사용하여 정리 하도록 하겠습니다.

개발 환경은 별도로 거론하지 않는다면 다음과 같습니다.


- Windows XP Platform

- Visual C++ 6.0

- OpenCV beta 5.0a



- 목 차 -

1. OpenCV 란 무엇인가?

2. OpenCV 설치하기

3. OpenCV 셋팅

 

- 본 문 -

1. OpenCV 란 무엇인가?

- OpenCV(Open Source Computer Vision) 인텔에서 만든 강력한 영상처리 라이브러리입니다.

- 기초 영상처리서부터 고급 수준의 영상처리 까지 상당한 량의 알고리즘들이 함수로 구현되어 있습니다.

- Binarization, Noise, Motion Detect, Edge Detect, Pattern Recognition, Hidden Markov Model 등등

- 오픈소스로서 스펙만 맞추면 자신의 알고리즘도 라이브러리에 등록 시킬 수 있습니다.

- 인텔의 OpenCV 사이트 http://www.intel.com/technology/computing/opencv/index.htm



2. OpenCV 설치하기

- OS Platform 에 맞게 OpenCV 라이브러리 다운받아 설치합니다.

- Linux 와 Windows 용이 있고 Mac OS 에서도 돌아간다고 합니다.

- 최신 OpenCV 가 Release 되는 곳

    http://sourceforge.net/projects/opencvlibrary


- 다운받기 OpenCV beta 5.0a for Window platform

    http://nchc.dl.sourceforge.net/sourceforge/opencvlibrary/OpenCV_b5a.exe

    http://keihanna.dl.sourceforge.net/sourceforge/opencvlibrary/OpenCV_b5a.exe



3. OpenCV 셋팅

기본적을 OpenCV 를 돌아가게 하려면 크게 4가지 작업을 해주어야 합니다.


1. 첫번째, Visual Studio 셋팅에서 디렉토리 추가하기

  개발 환경에서 컴파일러가 헤더 및 라이브러리 파일들을 찾을 수 있도록 한번만 셋팅해 주면 됩니다.


  - Include files

    C:\PROGRAM FILES\OPENCV\CXCORE\INCLUDE
    C:\PROGRAM FILES\OPENCV\CV\INCLUDE
    C:\PROGRAM FILES\OPENCV\OTHERLIBS\HIGHGUI
    C:\PROGRAM FILES\OPENCV\OTHERLIBS\CVCAM\INCLUDE


  - Library files

    C:\PROGRAM FILES\OPENCV\LIB


2. 두번째, 프로젝트에 Link 하기

  라이브러리 파일들을 링크 해 줍니다.

  원칙적으로는 소스 코드에 쓰인 라이브러리만 링크 해주면 되지만 일일이 어디에 속해 있는 함수인지 알기가 번거로움으로 일반적으로는 앞에 세가지를 기본적으로 링크하면 됩니다.

  cxcore.lib, cv.lib, highgui.lib, cvcam.lib


3. 세번째, 소스파일에 header 파일 include 하기

  #include <cv.h>

  #include <cxcore.h>

  #include <highgui.h>


4. 네번째, dll 파일 복사하기

  C:\Program Files\OpenCV\bin 폴더에서 다음과 같은 파일들을 Workspace 파일이 있는 폴더에 복사 합니다.

  만약에 라이브러리를 사용하지 않았을 경우에는 필요한 파일만 복사하면 됩니다.

    cv097.dll, cxcore097.dll, cvcam097.dll, highgui097.dll

아래 내용을 파일로 만들어 실행 파일에 있는곳에 집어 넣으면 간단히 해결된다...

VC에서 몇개 설정해야 되던걸 이렇게 간단히 해결할 수 있다니... ㅠㅠ...

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-     <assemblyxmlns="urn:schemas-microsoft-com:asm.v1"manifestVersion="1.0">
      <assemblyIdentity processorArchitecture="*"version="5.1.0.0"type="win32"name="Microsoft.Windows.Shell.shell32"/>
      <description>Windows Shell</description>
-     <dependency>
-     <dependentAssembly>
      <assemblyIdentity type="win32"name="Microsoft.Windows.Common-Controls"version="6.0.0.0"publicKeyToken="6595b64144ccf1df"language="*"processorArchitecture="*"/>
  </dependentAssembly>
   </dependency>
</assembly>

이 내용을 복사해서 "실행파일.exe.manifest"로 만들어 실행파일이 있는곳에 집어 넣으면 끝....
-------------------------------------------------------------------------------------
이런 소스가 귀찮다면... 볼랜드의 컴포넌트중.. XP Manifest 클래스를 떨어뜨려주기만해도.. 됨...
활성화만 시켜주면 바로 적용됨...

'1.소프트웨어 이야기 > 09.ETC' 카테고리의 다른 글

D 언어 소개  (0) 2007.12.06
두 점 사이의 각도 구하기  (0) 2007.12.06
문자열 처리 함수  (0) 2007.12.06


60분법 : 일반적으로 각의 크기를 나타내는 방법

● 호도법 : 원의 크기와는 관계없이 호의 길이와 반지름의 길이의 비가 일정하다는 원리를 이용하여, 이 비로 각의 크기를 나타내는 방법

 


반지름의 길이가 r인 원에서 크기가 θ인 중심각에 대한 호의 길이를 l이라고 하면,
l과 r의 비 l/r은 원의 크기에 관계없이 항상 일정하므로, ∠AOB의 크기를

 

l/r 라디안(radian)

으로 나타낼 수 있다.

즉, 반지름의 길이와 호 길이가 같을 경우  중심각의 크기는 1 라디안이다

 

180°= πr /r 라디안 = π 라디안

 

atan2() 함수는 라디안 값을 반환한다.



 
 

 

#include

#include


void main()

{

        double dX = 10;

        double dY = -10;

 

        printf("%lf\n", atan2( dY, dX ) * 180 / 3.14159265);

}

'1.소프트웨어 이야기 > 09.ETC' 카테고리의 다른 글

Manifest 적용하기..  (0) 2007.12.06
문자열 처리 함수  (0) 2007.12.06
윈도우 간단 메시지 보내기  (0) 2007.12.06
** 문자열 처리 함수 **

#include <string.h>


1) 문자열의 길이 측정(strlen)
    strlen(문자열)

2) 문자열 결합(strcat)
    char *ptr;
    ptr = strcat(문자열, 문자열2)

3) 문자열 비교(strcmp)

    int i;
    i = strcmp(문자열, 문자열2)
    i == 0 <--- 같다.
    i != 1 같지 않다.

4) 문자열 복사(strcpy)

    char *ptr;
    strcpy(문자열, 문자열2)|
    문자열2를 문자열로 복사

5) 문자열 변환(atoi, atol, atof)

    atoi -> 정수
    atol -> long
    atof -> 부동 소수점.    

    long b; float c;
    int a;
    a = atoi("1234");
    b = atol("-544334");
    c = atof("43.5456);

6) 문자열 교환 함수 (str_swap)

    void str_cpy(char *ptr1, char *ptr2)
    {
       while(*ptr2)
        *ptr1++ = *ptr2++;
        *ptr1 = NULL;
    }

    void str_swap(char *a, char *b)
    {
       char temp[255];
       str_cpy(temp, a);
       str_cpy(a, b);
       str_cpy(b, temp);
    }

7) 문자열 내에서 특정 문자의 개수를 카운트 하는 함수(char_cnt)

    int char_cnt(char *ptr, char ch)
    {
        int i = 0;
        while(*ptr)
         if(*ptr++ == ch)
            i++;
        return(i);
    } 

8) 문자열 내의 특정 문자를 다른 문자로 바꾸는 함수(str_chg)

    int str_chg(char *ptr, char ch1, char ch2)
    {
       while(*ptr)
       {
        if(*ptr == ch1)
           *ptr = ch2;
           ptr++;
       }
    }

9) 문자열 내의 특정 문자를 탐색(str_fine)

    char *str_find(char *ptr, char ch)
    {
       while(*ptr)
       {
        if(*ptr == ch)
           return(ptr);
        ptr++;
       }
       return((char *)(-1));
    }

10) 문자열 내의 소문자를 대문자로 바꾸는 함수(str_upp)

    void str_upp(char *ptr)
    {
       while(*ptr)
       {
        if(islower(*ptr))
           *ptr = toupper(*ptr);
        ptr++;
        }
    }

11) 문자열 내의 대문자를 소문자로 바꾸는 함수(str_low)

    void str_low(char *ptr)
    {
       while(*ptr)
       {
        if(isupper(*ptr))
           *ptr = tolower(*ptr);
        ptr++;
       }
    }

12) 대문자와 소문자 상호 교환 함수(str_case)

    void str_case(char *ptr)
    {
       while(*ptr)
       {
        if(isupper(*ptr))
           *ptr = tolower(*ptr);
        else if(islower(*ptr)
           *ptr = toupper(*ptr);
        ptr++;
       }
    }

13) 각 문장의 첫 문자만 대문자로 교환하는 함수(str_fst)

    void str_fst(char *ptr)
    {
        if(islower(*ptr))
        *ptr = toupper(*ptr);
        while(*ptr)
        {
           if(*ptr == '.')
          {
           ptr++;
           while(*ptr == ' ')
            ptr++;
           if(islower(*ptr))
            *ptr = toupper(*ptr);
          }
        }
        ptr++;
    }

14) 문자열 내의 지정한 위치에 다른 문자열을 삽입하는 함수(str_ins)

    char *str_ins(char ptr1[], char ptr2[],int t)
    {
       char temp[255];
       int i, j, k;
       if(t>=str_len(ptr1) return (-1);  
       for(k=0; i=0; i<t; i++; k++)
        temp[k] = ptr1[i];  

       for(j=0; ptr2[j] !=NULL; j++, k++)  
        temp[k] = ptr2[j];

       while(ptrl1[i])
        temp[k++] = ptr1[i++];

       temp[k] = NULL;
    }

15) 문자열 앞에 지정한 개수 만큼의 공백을 추가하는 함수(str_blk)

    void str_blk(char ptr[], int t)
    {
       static char temp[255];
       int i;
       for(i = 0; i<t; i++)
        temp[i] = BLANK;
       temp[i] = NULL;
       str_cat(temp ptr);
       str_cpy(ptr, temp);
    }

16) 문자열 내의 모든 공백을 삭제하는 함수(rmv_blk)

    void rmv_blk(char ptrp[])
    {
       char temp[255];
       int i, k;

       for(i=0, k=0; ptr[i] != NULL; i++)
        if(ptr[i] != BLANK)
           temp[k++] = ptr[i];
       temp[k] = NULL;
       str_cpy(ptr, temp);
    }

17) 문자열 내에서 원하는 개수 만큼 문자를 삭제하는 함수(str_rmv)

    void str_rmv(char *ptr, int loc, int count)
    {
       int len, i, j;
       len = str_len(ptr);
       if(loc >= len)
        return (-1);

       if(loc + count <= len)
       {
        j = loc + count;
        for(i=loc; ptr[j] != 0; i++)
        {
           ptr[i] = ptr[j];
           j++;
        }
            ptr[i] = NULL;
       }
       else
        ptr[loc] = NULL;
    }

18) 특정한 문자열이 기억된 위치를 계산하는 함수(str_loc)

    int str_loc(char ptr1[], char ptr2[])
    {
       int i, j, k;
       for(i=0; ptr1[i] != NULL; i++)
        for(j=i, k=0; ptr2[k] == ptr1[j]; k++, j++)
           return (i);
       return (-1);
    }


19) 특정한 문자열이 나온 개수를 카운트 하는 함수(str_cnt)

    int str_cnt(char ptr1[], char ptr2[])
    {
       int i, j, k;
       int count = 0;
       for(i=0; ptr1[i] != NULL; i++)
        for(j=i, k=0; ptr2[k] == ptr1[j]; k++, j++)
           if(ptr2[k+1] == NULL)
           {
            count++;
            break;
           }
        return ((count == 0) ? -1 : count);
    }

net send 192.168.0.1 하이

인터넷에서 찾아서 참고 하고 수정한 함수들...

/********************************************************************************************
한 비트값을 얻고자할때  index는 8bit 중 그 위치
GetBits (변수 ,  순서);  
7 6 5 | 4 3 2 1 0
GetBit(word,5); 5번째 값을 가져옴.. ^^
********************************************************************************************/
int GetBit (unsigned char data, int index) 
{
    unsigned char mask = 0x01;
    mask = mask << index;
    int i = data & mask;
    i = i >> index;
    return i;
}

/********************************************************************************************
2bit이상의 값을 추출할때 index(7-0)는 마지막 위치 ,  size는 가져오는 비트수
GetBits (변수 ,  5 , 3);  7 - 5까지 값을 가져옴.. ^^
7 6 5 | 4 3 2 1 0
********************************************************************************************/
int GetBits (unsigned char data, int index, int size) 
{
   unsigned char mask = 0xFF;
   mask = mask << (8-size);
   mask = mask >> (8-size);
   mask = mask << index;
   int i = data & mask;
   i = i >> index;
   return i;
}

// 형변환 모음
// CString형을 double형으로 변환
double CString2double(CString str)
{
   char *Temp = (LPSTR)(LPCSTR)str;
   return atof(Temp);
}

// double형을 CString형으로 변환
CString double2CString(double num)
{
   CString Temp;
  Temp.Format("%f", num);
  return Temp;
}

// CString형을 char* 형으로 바꾸는 함수
char *CString2char(CString str)
{
   char *charTemp = (LPSTR)(LPCSTR)str;
   return charTemp;
}


// 그외 형변환 참조 기존 자료들..
// int -> char *
Visual C++ 에는 다음과 같은 함수가 있습니다.
int , __int64 , unsigned __int64 등의 데이터형을 char* 형으로 바꾸어주는 함수들입니다.
인자에 대해 설명하자면 int value 는 입력값, char *string 은 출력값, int radix 는 출력될 진법을 표시합니다.
예를 들어 radix를 16으로 설정하면 16진수로 출력한다는 말이죠. radix 값은 2~36 사이의 값만 가능합니다.

char *_itoa( int value, char *string, int radix );
char *_i64toa( __int64 value, char *string, int radix );
char * _ui64toa( unsigned __int64 value, char *string, int radix );
wchar_t * _itow( int value, wchar_t *string, int radix );
wchar_t * _i64tow( __int64 value, wchar_t *string, int radix );
wchar_t * _ui64tow( unsigned __int64 value, wchar_t *string, int radix );

// char* 형을 double 형으로 바꾸는 함수
double atof( const char *string );

// char* 형을 int 형으로 바꾸는 함수
int atoi( const char *string );

// char* 형을 __int64 형으로 바꾸는 함수
__int64 _atoi64( const char *string );

// char* 형을 long 형으로 바꾸는 함수
long atol( const char *string );

'1.소프트웨어 이야기 > 09.ETC' 카테고리의 다른 글

두 점 사이의 각도 구하기  (0) 2007.12.06
문자열 처리 함수  (0) 2007.12.06
윈도우 간단 메시지 보내기  (0) 2007.12.06
CPort 설치 방법

Test 환경: Windows2000, C++ Builder 6.0

1.먼저 CPort 3.0 (cport-3.0.zip)을 다운로드 받는다.
   http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=component&no=366


2. 압축을 풀면 다음과 같은 파일이 생긴다.
    source.zip
    examples.zip
    help.zip
    locale.zip
  
3. 위의 4개 압축 파일을 차례대로 압축을 푼다.
   (ex)D:\DLTS_C\Component\CPort 3.0 이 디렉토리 하부에 풀었음.

4. C++ Builder를 기동하고 Source의 디렉토리의 bpk 파일을 연다
   본 PC에서는
  
   D:\DLTS_C\Component\CPort 3.0\sources\source\DsgnCPortCB6.bpk
   D:\DLTS_C\Component\CPort 3.0\sources\source\CPortLibCB6.bpk
  
   * 여러 개의 bpk 파일 나오는데.. 6.0에 해당하는 것은 이놈들인 것 같고..
   문제없다면 DsgnCPortCB6.bpk로 문제없는데.. 간혹 인스톨시 뭐라고 에러 나오는데..
   이 두개 파일을 번갈아 열어서 컴파일/인소톨하면 해결 됩니다. -.- 왜 그런 지는 저두 -.-;;

5. Compile하고 install 한다. install까지 정상적이라면 컴포넌트 갤러리 창에 새로운
   탭이 하나 더 생기고 몇 개의 아이콘이 보일 것이다. 그리고,

   C:\Program Files\Borland\CBuilder6\Projects\Bpl
   C:\Program Files\Borland\CBuilder6\Projects\Lib

   디렉토리에 CPort관련 bli, lib 파일들이 생성된다.

6. 다음 파일을 수정한다. 수정하지 않으면 컴파일 시, 링크 시 낭패를 보게 된다.

   D:\DLTS_C\Component\CPort 3.0\sources\source\CPort.hpp
   D:\DLTS_C\Component\CPort 3.0\sources\source\CPortCtl.hpp

   파일을 수정한다. 수정없이 사용하면
   동일한 함수가 두번 정의됐다는 메세지와 함께 에러가 발생한다.

   [CPort.hpp]
          // 1. 파일 맨 윗부분에 다음을 추가한다.

       // Borland C++ Builder
       // Copyright (c) 1995, 2002 by Borland Software Corporation
       // All rights reserved

       // (DO NOT EDIT: machine generated header) 'CPort.pas' rev: 6.00

       #undef SetPort       // <= 이부분 추가 : 안하면 ComPort->SetPort("COM1");
                //                  이런 문장에서 Link 에러 발생


       // 2. 다음 2개의 함수를 주석 처리한다. (680라인 정도에 있음)
       /* Exception.CreateRes */ inline __fastcall EComPort(int Ident)/* overload */ : Sysutils::Exception(Ident) { }
       /* Exception.CreateResHelp */ inline __fastcall EComPort(int Ident, int AHelpContext)/* overload */ : Sysutils::Exception(Ident, AHelpContext) { }


   [CPortCtl.hpp]
           // 아래의 부분을 주석으로 처리 (240라인 정도에 있음)
       //typedef TBitmap TLedBitmap;
       //;

7. 두 개의 파일을 수정하였으면 Source 디렉토리에 있는 모든 *.hpp 파일을
   C:\Program Files\Borland\CBuilder6\Include\Vcl 로 복사

   이렇게 하면 일단 설치가 완료됨.


8. 이 후 프로젝트에서 Cport를 이용하려 할 때 다음과 같이 한다.
    8.1 Project -> Option 에서 Directories/Conditionals 탭을 연다.
    8.2 Library Path에
        D:\DLTS_C\Component\CPort 3.0\sources\source\ 디렉토리를 추가하여 준다.

    이거 안 해주면 또 xxxx.DFM 파일이 없네...뭐 어쩌내 하면서 링커 에러 또 나옴.

    8.3 Library Path에 추가시키면 그냥 사용하면 됨.

9. 참고로 볼란드 포럼에 CPort에 관한 많은 Q/A가 있으므로 이 것을 토대로 코딩하면
   될 것 같음.
  
* 참고
상기의 7,8,9번은 컴파일/링크 시 헤더 파일과 리소스 파일의 디렉토리를 어떤 식으로든 컴파일러에
알려 주기만 하면 됩니다.
  즉, install하고 난 후 header 파일 고치고(xxxx.hpp), 관련된 모든 파일을 자신이 개발하는
소스 디렉토리에 몽땅 카피하고, include 와 lib 디렉토리에 현재 디렉토리를 정해주면 문제없이
됩니다.
  즉, xxxx.hpp 파일, xxxx.dfm 파일, xxxx.res 파일(CPortImg.res)을 현재 개발 소스가 있는
디렉토리에 모두 복사하고, Project -> Option 에서 Directories/Conditionals 탭에서 include와
lib 디렉토리를 현재 디렉토리를 추가(default로 현재 디렉토리가 있음)하면 됩니다. 이 방법이
위의 7,8번의 과정을 거치지 않아서 좀더 간편한 방법 같습니다.
  아니면 모든 연관된 파일을 Program Files\Borland 쪽으로 가져다 놓는 것인데.. Builder 다시 깔고
뭐 이리 저리 왔다갔다 하는 과정에서 보니-제경우 좀 불편한 면이 있어서요..
  아뭏튼 구미에 맞게 사용하시길...

**
참고로 Cport-3.0.zip에 있는 CBuilder용 example은 5.0으로 되어 있으며 6.0에서
컴파일 시 이런 저런 에러가 발생하였으며 Lib 파일도 5.0으로 빌드된 파일을 찾고 해서,
이래 저래 실행해보지 못했음. 단, 코드 정도는 참고할 정도가 됨.

-볼랜드포럼에서 발췌 -
1) Uninstall Delphi 2007.

2) Remove the Program Files\CodeGear\RAD Studio\5.0 directory.

For Windows Vista:

3a) Remove the Program Data\CodeGear\RAD Studio\5.0 directory.

3b) Remove the Program Data\{AB3EC276... directory.

3c) Remove the User\All Users\CodeGear\RAD Studio\5.0 directory.

For pre-Vista Windows OS:

3a) Remove the Documents and Setting\All Users\Application Data\CodeGear\RAD Studio\5.0 directory.

3b) Remove the Documents and Setting\All Users\Application Data\{AB3EC276... directory.

4) If you had the Trial or Enterprise version installed and are now installing the Professional version, then run Regedit and remove the key: HKEY_CURRENT_USER\Software\Borland\BDS\5.0

5) Re-install Delphi 2007.

+ Recent posts