2016년 12월 30일 금요일

OpenCV 정리

CvPoint : 두 개의 정수형 멤버 x, y
CvPoint2D32f : 두 개의 실수형 멤버 x, y
CvPoint3D32f : 세 개의 실수형 멤버 x, y, z

CvSize : CvPoint 의 사촌격. 정수형 멤버 width, height
CvSize2D32f : 실수형 width, height

CvRect : 네 개의 정수형 멤버, x, y, width, height

CvScalar : 네개의 double형 실수값을 배열 형태로 가지고 있다. double형 배열 val을 멤버로 가지고 있다.

CvArr --> CvMat --> IplImage

CvMat*  cvCreateMat( int rows, int cols, int type );
type : CV_<비트수>(S|U|F)C<채널 개수>

* IplImage 의 데이터 접근
IplImage 구조체는 ImageData라는 char**형 이미지 저장 장소를 지원합니다.

위의 예를 따르자면 image->ImageData 와 같이 접근 가능합니다.

1)컬러 영상 : 일반적으로 32bit 이미지로, 각 Blue, Green, Red 영역 순으로 기록
for(int i = 0; i < image->widthstep; i += image->nChannels)
     for(int j = 0; j < image->height; j++)
     {
          image->ImageData[i + j * image->widthstep) = xxxx; // blue 영역
          image->ImageData[i + j * image->widthstep + 1) = xxxx; // green 영역
          image->ImageData[i + j * image->widthstep + 2) = xxxx; // red 영역
     }

2)1채널 영상
for(j = 0; j < image->height; j++)
     for(i = 0; i < image->width; i++)
          tmpBuf[j * image->width + i] = (unsigned char) image->imageData[j * image->widthStep + i];

*tmpBuf( unsigned char* tmpBuf = new unsigned char [nWidth * nHeight];)는 영상 값

lPlImage *image = cvLoadImage(filename) ;

1 channel gray 영상의 경우:
int index = x + y*image->widthStep ;
unsigned char value = image->imageData[index] ;

3 channel RGB 영상의 경우:
int index = 3*x + y*widthStep ;
unsigned char B = image->imageData[index] ;
unsigned char G = image->imageData[index+1] ;
unsigned char R = image->imageData[index+2] ;

또 다른 방법은 OpenCV가 제공하는 cvGet 함수를 이용하는 것이다. 1채널 Gray 영상에는 cvGetReal2D() 함수를, 다채널 영상에는 cvGet2D()를 사용한다. cvGetReal2D 함수는 double 값을, cvGet2D는 CvScalar 구조체에 각 채널별로 값을 저장해서 리턴한다. 함수의 인자에 x와 y의 순서에 주의한다.

1 channel gray 영상의 경우
double value = cvGetReal2D(image, y, x) ;

3 channel RGB 영상의 경우
CvScalar value = cvGet2D(image, y, x) ;
double B = value.val[0];
double G = value.val[1];
double R = value.val[2];

* CvMat 의 데이터 접근
1. at 접근 방법
Mat image(ROW, COL, CV_TYPE);
image.at<DATA_TYPE>(WANT_ROW, WANT_COL);
- ROW : 행
- COL : 열
- CV_TYPE : 데이터 타입(예: CV_8UC3 = 8 bit 3 channels)
- DATA_TYPE : Mat 생성시 데이터 타입(예: float, usigned char)
- WANT_ROW : 접근하기 원하는 행
- WANT_COL : 접근하기 원하는 열

2. ptr 접근 방법
Mat image(ROW, COL, CV_TYPE);
image.ptr<DATA_TYPE>(WANT_ROW, WANT_COL); (포인터형으로 반환하기때문에 이에 맞는 포인터 변수를 사용해서 접근해야함)
- ROW : 행
- COL : 열
- CV_TYPE : 데이터 타입(예: CV_8UC3 = 8 bit 3 channels)
- DATA_TYPE : Mat 생성시 데이터 타입(예: float, usigned char)
- WANT_ROW : 접근하기 원하는 행
- WANT_COL : 접근하기 원하는 열

3. data 접근 방법
Mat image(ROW, COL, CV_TYPE);
DATA_TYPE* data = (DATA_TYPE*)image.data;
data[WANT_ROW *  image.cols + WANT_COL]
- ROW : 행
- COL : 열
- CV_TYPE : 데이터 타입(예: CV_8UC3 = 8 bit 3 channels)
- DATA_TYPE : Mat 생성시 데이터 타입(예: float, usigned char)
- WANT_ROW : 접근하기 원하는 행
- WANT_COL : 접근하기 원하는 열

* IplImage 관련,  생성과 해제
//생성
IplImage *srcimg_R  = NULL;
srcimg_R  = cvCreateImage(cvSize(m_width,m_height), 8, 3);   //cvSize(640,480) 같은 것도 됨
srcimg_R  = cvCreateImage(cvGetSize(src_color), 8,3);  //요것도 됨.  다른 IplImage 사이즈 받아와서

//요런것도 됨
CvSize img_size;
img_size.height = ImageHeight;
img_size.width  = ImageWidth;

IplImage* BGR_image = cvCreateImage(img_size, IPL_DEPTH_8U, 3);

//이미지 복사하기
src = cvCloneImage(src_img);  //src가 비어있어야 함.  아니면 메모리 계속 쌓인다
cvCopy(src_img, src_img2);

//컬러 이미지 각 소스별로 분리하거나 합치거나 할 때
cvCvtPixToPlane( src_hlsimg, Hue, Intensity, Saturation, NULL );  //HLS 이미지 각 속성별로 나눔
cvCvtPlaneToPix( Hue, Intensity, Saturation, NULL, Equ_hls );  //다시 합친다

//0으로 초기화
cvZero(src_img);

//해제
if(srcimg_R)
  cvReleaseImage(&srcimg_R);

* 이미지 불러오기, 저장하기
//불러오기
TmpLImg = cvLoadImage("img_InElevator_1_L.bmp");    //간단하게, TmpLImg는 IplImage
//복잡하게
if ((TmpLImg = cvLoadImage("img_InElevator_1_L.bmp")) == 0)  // load left image
{
   printf("%s", "left image file read has failed!! \n");
   return 0;
}

//저장하기
char file_name[20];
sprintf(file_name,"img_R.bmp");            //파일이름 맹글기
cvSaveImage(file_name,srcimg_R);   //srcimg_R 이라는 IplImage를 저장

* 창 만들고 닫기 등등
//생성
cvNamedWindow("Right Original", CV_WINDOW_AUTOSIZE);

//창 움직이기 - uv 좌표로 배치함
cvMoveWindow("source_color",610,0);

//보이기
cvShowImage( "Right Original", srcimg_R );

//창 닫기
cvDestroyAllWindows();  //모든 OpenCV 윈도우 닫기

//특정 윈도우만 닫기
cvDestroyWindow("Right Original");

* canny edge detect
IplImage *canny_R   = NULL;
canny_R    = cvCreateImage(cvSize(m_width,m_height), 8, 1);
...
cvCvtColor(srcimg_R, grayimg_R, CV_BGR2GRAY);   //원본 컬러이미지를 흑백으로 변환하고

cvCanny( grayimg_R, canny_R, 40, 130, 3 );  //그 흑백이미지를 캐니로 변환

* Harris edge detector
IplImage *harris = cvCreateImage(cvSize(WIDTH,HEIGHT), IPL_DEPTH_32F, 1);
cvCornerHarris(src_gray, harris, 3, 9, 0.07);

* Smoothing 연산
//Gaussian filtering
cvSmooth(src, Gaussed_image, CV_GAUSSIAN, 3);  //src는 gray영상, 두번째 매개변수도 IplImage임, 3은 마스크 크기

//DoG(Difference of Gaussian)
cvSmooth(src_gray, GaussImg1, CV_GAUSSIAN, 3);
cvSmooth(src_gray, GaussImg2, CV_GAUSSIAN, 27);
cvSub(GaussImg1, GaussImg2, dst);

* 키 입력
pressed_key=cvWaitKey(0) ;
  if(pressed_key=='q')    //q 키가 누르면 빠져나가기
    break;
  else if(pressed_key=='c')  //캡쳐 키 누르면 캡쳐
  {
    timer=time(NULL);  //현재시간저장
    t=localtime(&timer); //지역시간
    sprintf(file_name,"img_%4d%02d%02d%02d%02d%2d.bmp",t->tm_year + 1900, t->tm_mon +1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);

    cvSaveImage(file_name, src_color);

    //확인메시지출력
    printf("%s file saved is success!!\n",file_name);
  }

* 화면에 글자 쓰기
char s_output_result[50];
CvFont font;
...
sprintf(s_output_result,"sum vector x:%1.3f  y:%1.3f",sumvector_x,sumvector_y );    //우선 sprintf로 문자열 생성
cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC, 0.5, 0.5, 0, 1);  //이런 저런 설정.
cvPutText(src_color, s_output_result ,cvPoint(15,20),&font,cvScalar(0,255,0));   //cvPoint로 글자 시작 위치 설정(uv)
//void cvInitFont(CvFont* font, int font_face, double hscale, double vscale, double italic_scale, int thickness)

* 트랙바 생성
int hue_threshold=139;  //Hue 값의 피부색 threshold

cvNamedWindow( "HLS_image", CV_WINDOW_AUTOSIZE );
cvCreateTrackbar("Hue","HLS_image",&hue_threshold,255, NULL );  //중요한 부분은 요거

* 마우스 입력
void on_mouse( int event, int x, int y, int flags, void* param );
......

cvSetMouseCallback( "LKTracker", on_mouse, NULL );
......

void on_mouse( int event, int x, int y, int flags, void* param )
{
    if( !image )
        return;

    if( image->origin )
        y = image->height - y;

    if( event == CV_EVENT_LBUTTONDOWN )
    {
        pt = cvPoint(x,y);
        add_remove_pt = 1;
    }
}

* IPP 검사
    const char* libraries;
    const char* modules;
    cvGetModuleInfo( 0, &libraries, &modules );
    printf("Libraries: %s\nModules: %s\n", libraries, modules );

댓글 없음:

댓글 쓰기