'프로그램/opencv'에 해당되는 글 2건

high gui

프로그램/opencv 2015.07.08 16:43

1. 이식성있는 그래픽 툴킷


openCV에서 카메라와 같은 하드웨어, 또는 파일 시스템, 운영체제 등과 연관된 작업을 지원하는 함수들은 모두 HighGUI라는 이름의 라이브러리에 포함되어 있다..




2. 윈도우


cvNamedWindow() - 윈도우 생성

cvDestroyWindow() - 윈도우 제거 


3. 영상 불러오기


IplImage* cvLoadImage(const char* filename, int iscolor) - 영상 불러오기.


int cvSaveImage(const char* filename, const CvArr* image) - 영상 저장.



4. 화면에 영상 출력


cvShowImage(const char* name, const CvArr* image);



추후작성.



'프로그램 > opencv' 카테고리의 다른 글

high gui  (0) 2015.07.08
opencv 기초  (2) 2015.07.03
블로그 이미지

종환 Revolutionist-JongHwan

github.com/alciakng 항상 겸손하자.

댓글을 달아 주세요


* 스칼라 벡터에 대한 구조체 정의


 cvPoint

 int x,y

 영상 내 한 점의 위치

 cvPoint2D32f

 float x,y

 2차원 실수 공간에서의 좌표

 cvPoint3D32f

 float x,y,z

 3차원 실수 공간에서의 좌표

 cvSize

 int width,height

 영상의 크기

 cvScalar

 double val[4]

 RGB값


openCV는 주로 IplImage 데이터 타입을 사용한다. IplImage는 '영상'이라고 부르는 것을 표현하는 데이터 타입이다. 


이러한 IplImage 데이터타입은 cvArr로 부터 상속된 구조를 갖는다 .cvArr->cvMat->IplImage


OpenCV에서 행렬은 32비트 실수형 1채널(CV_32FC1), 부호없는 8비트 정수형 3채널(CV_8UC3) 등 여러 데이터 타입으로 구성될 수 있다. 


이러한 행렬을 만드는 함수는 cvCreateMat(int rows,int cols,int type)을 쓴다. 


행렬을 만들고 나서 행렬의 속성을 알아보기 위해서 cvGetElemType(), cvGetDims(), cvGetDimSize()등의 함수를 사용한다.



* 행렬 데이터 접근하기 


1. 간편한 방법


CV_MAT_ELEM() 과 CV_MAT_ELEM_PTR() 매크로를 이용한다 .


2. 엄격한 방법


cvPtr*D 또는 cvGet*D 형태의 함수를 사용한다.


ex)  uchar* cvPtr1D(const CvArr* arr,int idx0, int* type=NULL);

ex)  double cvGetReal1D(const CvArr* arr,int idx0);


cvGet*D와 유사한 cvSet*D 형태의 함수는 행렬 또는 영상의 특정 위치 원소값을 설정하는 함수이다.


ex) void cvSetReal1D(CvArr* arr, int idx0, double value);

    void cvSetReal2D(CvArr* arr, int idx0, int idx1, double value);


3.적절한 방법


앞서 행렬 데이터를 조작하는 다양한 접근 함수를 알아보았지만 거의 사용하지 않는다.

보통 행렬의 데이터를 접근할 때, 포인터를 통한 접근을 우선시한다.


float sum(const CvMat* mat)

{

float s = 0.0f;


for(int row=0;row<mat->rows;row++)

{

const float* ptr(const float*)(mat->data.ptr+row*mat->step);


for(col=0;col<mat->cols;col++)

s+=*ptr++;

}


return(s);

}



IplImage 구조체 


중요변수 -> width, height, depth, nChannels, origin, dataOrder,widthStep


nChannels ->픽셀의 채널 수. 

depth -> 데이터의 타입.

origin -> IPL_ORIGIN_TL(0), IPL_ORIGIN_BL(1) 중 하나를 가질 수 있다. 영상에서 좌표의 원점이 좌상단에 위치하는 지 좌하단에 위치하는지를 가리킨다. 

dataOrder  -> IPL_DATA_ORDER_PIXEL 또는 IPL_DATA_ORDER_PLANE 중에 하나를 지정한다 . 이 값이 IPL_DATA_ORDER_PIXEL이면 다중채널값을 차례대로 가지고 있고 , 일반적인 인터리브 방식이다 . 만약 dataOrder가 IPL_DATA_ORDER_PLANE값을 가지면 각 채널 별로 따로 픽셀값이 저장된다.(일반적으로 인터리브 방식사용한다. 행의 개수 = 영상의 높이, 각 행에서는 각 채널값이 교차된 순서로 나타난다.)

widthStep -> 한 행이 실제로 차지하고 있는 바이트 수.

imageData -> 영상 데이터의 시작 주소를 가리킨다. 


#관심영역(roi)  --> 영상 내부에 roi가 설정되어 있을 경우, 영상을 다루는 함수는 영상 전체에 대하여 동작하는 대신 roi로 설정된 영역에서만 동작한다. 모든 opencv 함수는 roi 설정 여부를 스스로 판단하여 동작한다 .



* 영상데이터 접근하기


OpenCV 라이브러리가 영상 처리와 관련된 다양한 함수들을 제공하지만 실제 작업에서 필요한 모든 함수들을 완벽하게 제공할 수는 없다. 예를 들어, 3채널 HSV 영상에서 색상값은 그대로 둔 채 채도와 명도값을 모두 255로 설정하는 작업은 행렬을 이용하여 영상자체를 가리키는 포인터를 이용하여 수행하는것이 효과적이다.


HSV 영상에서 "S"와 "V"에 해당하는 값을 최대화


void saturate_sv(IplImage* img)

{

for(int y=0;y<img->height;y++)

{

uchar* ptr = (uchar*)(img->imageData + y*img->widthStep);


for(int x=0;x<img->width;x++)

{

//ptr [3*x]는 h값을 나타낸다.

ptr[3*x+1] = 255;

ptr[3*x+2] = 255;

}

}



* roi를 설정하는 두가지 방법.


1. void cvSetImageROI(IplImage* image,CvRect rect);

   void cvResetImageROI(IplImage* image);


#include 
#include 

int main()
{
      IplImage* src = cvLoadImage("~~",1);

      cvSetImageROI(src, cvRect(x,y,width,height));
      cvAddS(src, cvScalar(add),src);
      cvRestImageROI(src);

      cvNamedWindow("Roi_Add", 1);
      cvShowIamge("Roi_Add", src);
      cvWaitKey();

      cvReleaseImage(&src);
      cvDestroyWindow("Roi_Add");
}
      return 0;
}
      

2. widthStep을 이용하여 관심 영역을 처리하는 대체방법

IplImage *sub_img = cvCreateImageHeader(
     cvSize(
           interest_rect.width,
           interest_rect.height
     ),
     interest_img->depth,
     interest_img->nChannels
);

sub_img->origin = interest_img->origin;

sub_img->widthStep = interest_img->widthStep;

sub_img->imageData = interest_img->imageData + interest_rect.y * interest_imag->widthStep + interest_rect.x * interest_img->nChannels;

cvAddS(sub_img,cvScalar(1),sub_img);

이하 다양한 함수들은 생략하고 필요할 때마다 참조하여 공부한다

아래는 연습문제 예제이다. 개인적으로 2,4,5,6,7 번이 중요하다고 생각한다.

#include

#include #include typedef struct my_struct{ int a; CvPoint b; CvRect c; }my_struct; void write_my_struct(CvFileStorage* fs, const char* name, my_struct *ms); void read_my_struct(CvFileStorage* fs, my_struct *ms); int main() { /01번 CvMat* mat = cvCreateMat(1,1,CV_32FC3); CvMat* dst = cvCreateMat(1,1,CV_32FC3); *((float*)CV_MAT_ELEM_PTR(*mat, 0, 0)) = 0; //a cvAbs(mat, dst); //b CvMat* noise = cvCreateMat(10, 1, CV_64FC1); CvRNG rng[] = { cvRNG(time(NULL)), cvRNG(time(NULL)) }; cvRandArr(rng, noise, CV_RAND_NORMAL, cvScalarAll(0), cvScalarAll(0)); //c,d CvPoint((int)CvPoint2D32f(3.0, 2.0).x,(int)CvPoint2D32f(3.0, 2.0).y); cvPoint2D32f((float)cvPoint(3,2).x,(float)cvPoint(3,2).y); / /02번 - 100*100 3채널 2차원 행렬 생성후 원그리고 출력. CvMat* mat = cvCreateMat(100,100,CV_8UC3); cvSet(mat, cvScalarAll(255)); cvCircle(mat, cvPoint(50, 50), 40, CV_RGB(0, 0, 250)); cvNamedWindow("Drawing Graphics", CV_WINDOW_AUTOSIZE); cvShowImage("Drawing Graphics", mat); cvWaitKey(0); / /04번- 100*100 3채널 RGB영상을 생성하고 흰색초기화후 포인터 연산을 통한 녹색사각형 출력 IplImage* src = cvCreateImage(cvSize(100, 100), , 3);; cvSet(src, cvScalarAll(255)); for (int i = 20; i < 40; i++){ uchar* ptr = (uchar*)(src->imageData+i*src->widthStep); for (int j = 5; j < 20; j++){ ptr[3 * j] = 0; ptr[3*j+1] = 150; ptr[3 * j + 2] = 0; } } cvNamedWindow("Drawing Graphics", CV_WINDOW_AUTOSIZE); cvShowImage("Drawing Graphics", src); cvWaitKey(0); / /05번 - 관심영역연습. IplImage* src = cvCreateImage(cvSize(210, 210), IPL_DEPTH_8U, 1); cvSet(src, cvScalarAll(0)); for (int i = 0; i < 110; i += 10){ cvSetImageROI(src, cvRect(i, i, 210-2*i, 210 - 2 * i)); cvSet(src, cvScalarAll(2 * i)); } cvResetImageROI(src); cvNamedWindow("5번", 1); cvShowImage("5번", src); cvWaitKey(); cvReleaseImage(&src); cvDestroyWindow("5번"); / /6번 - cvNot 활용. IplImage* src = cvLoadImage("C:/Users/Jonghwan123/Documents/카카오톡 받은 파일/opencv.jpg"); IplImage* dst1 = cvCreateImageHeader(cvSize(20,30), src->depth, src->nChannels); IplImage* dst2 = cvCreateImageHeader(cvSize(20,30), src->depth, src->nChannels); dst1->origin = src->origin; dst2->origin = src->origin; dst1->widthStep = src->widthStep; dst2->widthStep = src->widthStep; dst1->imageData = src->imageData + 10*src->widthStep + 10*src->nChannels; dst2->imageData = src->imageData + 60*src->widthStep + 50 *src->nChannels; cvNot(dst1,dst1); cvNot(dst2,dst2); cvNamedWindow("6번", 1); cvShowImage("6번", src); cvWaitKey(); / /7번 - 임계값을 구하고 임계값을 통한 cvCmp cvSubS 활용. IplImage* src = cvLoadImage("C:/Users/Jonghwan123/Documents/카카오톡 받은 파일/opencv.jpg"); IplImage* dst1 = cvCreateImage(cvSize(src->width,src->height),src->depth,1); IplImage* dst2 = cvCreateImage(cvSize(src->width,src->height),src->depth,1); IplImage* dst3 = cvCreateImage(cvSize(src->width,src->height),src->depth,1); cvSplit(src, dst1, dst2, dst3, NULL); IplImage* clone1 = cvCreateImage(cvSize(dst1->width, dst1->height), dst1->depth, 1); IplImage* clone2 = cvCreateImage(cvSize(dst1->width, dst1->height), dst1->depth, 1); double min = 0; double max = 0; cvMinMaxLoc(dst1, &min, &max, NULL, NULL, NULL); unsigned char thresh = (unsigned char)((max + min) / 2.0)+100; cvSet(clone1, cvScalar(thresh)); cvSet(clone2, cvScalar(0)); cvCmp(dst1, clone1, clone2, CV_CMP_GE); cvSubS(dst1, thresh / 2, dst1, clone2); cvNamedWindow("7번", 1); cvShowImage("7번", clone2); cvWaitKey(); / /8번 my_struct ms = { 1, { 20, 30 }, { 20, 30, 10, 20 } }; //CvFileStorage* wfs = cvOpenFileStorage("cfg.xml", 0, CV_STORAGE_WRITE); CvFileStorage* rfs = cvOpenFileStorage("cfg.xml", 0,CV_STORAGE_READ); //write_my_struct(wfs, "jonghwan",&ms); //CvSeq* s = cvGetFileNodeByName(rfs, 0, "jonghwan")->data.seq; //CvFileNode* filenode = (CvFileNode*)cvGetSeqElem(s,0); read_my_struct(rfs, &ms); / } //8번함수1 void write_my_struct(CvFileStorage* fs, const char* name, my_struct *ms){ cvWriteInt(fs, "a", ms->a); cvStartWriteStruct(fs, "b", CV_NODE_SEQ); cvWriteInt(fs, 0, ms->b.x); cvWriteInt(fs, 0, ms->b.y); cvEndWriteStruct(fs); cvStartWriteStruct(fs, "c", CV_NODE_SEQ); cvWriteInt(fs, 0, ms->c.x); cvWriteInt(fs, 0, ms->c.y); cvWriteInt(fs, 0, ms->c.width); cvWriteInt(fs, 0, ms->c.height); cvEndWriteStruct(fs); cvReleaseFileStorage(&fs); //cvWrite(fs, "b", &ms->b); //cvWrite(fs, "c", &ms->c); } //8번함수2 void read_my_struct(CvFileStorage* fs, my_struct *ms){ int a = cvReadIntByName(fs, 0, "a", 5); CvSeq* b = cvGetFileNodeByName(fs, 0, "b")->data.seq; int bx = cvReadInt((CvFileNode*)cvGetSeqElem(b, 0)); int by = cvReadInt((CvFileNode*)cvGetSeqElem(b, 1)); CvSeq* c = cvGetFileNodeByName(fs, 0, "c")->data.seq; int cx = cvReadInt((CvFileNode*)cvGetSeqElem(c, 0)); int cy = cvReadInt((CvFileNode*)cvGetSeqElem(c, 1)); int width = cvReadInt((CvFileNode*)cvGetSeqElem(c, 2)); int height = cvReadInt((CvFileNode*)cvGetSeqElem(c, 3)); //printf("%d", frame_count); }


'프로그램 > opencv' 카테고리의 다른 글

high gui  (0) 2015.07.08
opencv 기초  (2) 2015.07.03
블로그 이미지

종환 Revolutionist-JongHwan

github.com/alciakng 항상 겸손하자.

댓글을 달아 주세요