http://kimhj8574.egloos.com/4734597
*** 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);
//0으로 초기화
cvZero(src_img);
//해제
if(srcimg_R)
cvReleaseImage(&srcimg_R);
*** IplImage 안의 이미지 화소 조절하기
* 간단하지만 속도가 좀 느린 방법
cvGetReal2D(srcimg, i, j); //높이가 i, 폭이 j
cvSetReal2D(srcimg, i, j, value); //value는 설정할 값
* 약간 복잡하지만 속도가 빠른 방법 (추가)
for(h=0; h<img->height; ++h)
{
BYTE* pData = (BYTE*)(img->imageData + h*imgData->widthStep);
for(w=0; w<img->width; ++w)
{
// gray image
BYTE valGray = pData[w];
// color image (BGR 순서입니다.)
BYTE valB = pData[w*3];
BYTE valG = pData[w*3+1];
BYTE valR = pData[w*3+2];
}
}
*** 이미지 불러오기, 저장하기
//불러오기
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 ); //그 흑백이미지를 캐니로 변환
*** HLS 이미지로 변환하기
...
IplImage* src_hlsimg = cvCreateImage(cvSize(m_width,m_height), 8, 3); //HLS 저장할 곳
//각 속성들 저장할 곳 선언
IplImage* Hue = cvCreateImage(cvSize(m_width,m_height), 8, 1);
IplImage* Intensity = cvCreateImage(cvSize(m_width,m_height), 8, 1);
IplImage* Saturation = cvCreateImage(cvSize(m_width,m_height), 8, 1);
cvCvtColor(srcimg, src_hlsimg, CV_BGR2HLS); //src_hlsimg IplImage 구조체에 HLS 이미지 담긴다
cvCvtPixToPlane( src_hlsimg, Hue, Intensity, Saturation, NULL ); //HLS 이미지 각 속성별로 나눔
cvCvtPlaneToPix( Hue, Intensity, Saturation, NULL, hsvVideo2 ); //도로 합치기
*** 창으로 부터 키 입력 받기
...
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);
}
*** 이미지 크기 줄이기
//생성
pEviMonitor = cvCreateImage(cvSize(m_pImgWidth, m_pImgHeight), IPL_DEPTH_8U, 1);
pEviMonitor2 = cvCreateImage(cvSize(m_pImgWidth/2, m_pImgHeight/2), IPL_DEPTH_8U, 1); // 1/2 크기로 생성
//크기 줄이기
cvResize(pEviMonitor, pEviMonitor2, CV_INTER_LINEAR); // For Resize
*** 화면에 글자 쓰기
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;
}
}
*** 인클루드 하는 것들
#include <cv.h> //영상처리를 위한 헤더
#include <highgui.h> //카메라로 영상을 입력받거나 이미지를 읽어들이고 화면에 보여주기 위한 헤더
*** good feature to track
IplImage *eig_image = NULL;
IplImage *temp_image = NULL;
eig_image = cvCreateImage(cvSize(width,height), 32, 1);
temp_image = cvCreateImage(cvSize(width,height), 32, 1);
CvPoint2D32f frame1_features[4000]; //추출된 점들 저장하는 장소
int number_of_features;
number_of_features = 400; //추출되는 점의 개수를 제한
//안됨. 버전마다 매개변수 다른듯
//cvGoodFeaturesToTrack(src_gray, eig_image, temp_image, frame1_features, &number_of_features, .01, .01, NULL);
cvGoodFeaturesToTrack(src_gray, eig_image, temp_image, frame1_features, &number_of_features, 0.01, 5, 0, 3, 0, 0.04 );
//&number_of_features 로 추출된 점의 개수 나온다. 추출되는 점의 개수를 입력으로 제한함과 동시에 출력도...
*** 캠 입력받기
IplImage *src; //source 이미지니까 src로 이름지음
//capture for cam
CvCapture* capture = cvCaptureFromCAM(0);
//get init scene
cvGrabFrame(capture);
src=cvRetrieveFrame(capture);
......
cvGrabFrame(capture);
src=cvRetrieveFrame(capture);
......
cvReleaseCapture( &capture );
//다른 방법
IplImage *src;
CvCapture* capture = cvCaptureFromCAM(0);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH,640); //잘 안됨
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT,480);
...
src = cvQueryFrame( capture );.
...
// 또다른 방법 (추가)
VidFormat vidFmt = { 1600, 1200, 7.5 }; // 캠 영상의 실제 크기 및 Frame Rate
int nSelected = cvcamGetCamerasCount();
if( nSelected != 0 )
{
CRect rtWndCam;
int nDispWidth, nDispHeight;
CWnd* pWndCam = GetDlgItem(IDC_STATIC_CAM);
pWndCam->GetWindowRect(&rtWndCam);
nDispWidth = rtWndCam.Width();
nDispHeight = rtWndCam.Height();
cvcamSetProperty(0, CVCAM_PROP_ENABLE, CVCAMTRUE);
cvcamSetProperty(0, CVCAM_PROP_SETFORMAT, &vidFmt); // 미리 설정된 값으로 고정
// cvcamGetProperty(0, CVCAM_VIDEOFORMAT, NULL); // 시작할때 선택 가능
cvcamSetProperty(0, CVCAM_PROP_RENDER, CVCAMTRUE);
cvcamSetProperty(0, CVCAM_PROP_WINDOW, &pWndCam->m_hWnd);
cvcamSetProperty(0, CVCAM_RNDWIDTH, &nDispWidth);
cvcamSetProperty(0, CVCAM_RNDHEIGHT, &nDispHeight);
cvcamSetProperty(0, CVCAM_PROP_CALLBACK, CallBackCam);
cvcamInit();
cvcamStart();
}
else
{
MessageBox("카메라가 연결되어 있지 않습니다.");
}
*** Optical Flow
voidcvCalcOpticalFlowPyrLK(
const CvArr* prev, // 첫 번째 이미지
const CvArr* curr, // 두 번째 이미지
CvArr* prev_pyr, // 첫 번째 이미지의 피라미드
CvArr* curr_pyr, // 두 번째 이미지의 피라미드
const CvPoint2D32f* prev_features, // 첫 번째 이미지에서 원래 점의 위치
CvPoint2D32f* curr_features, // 두 번째 이미지에서 찾은 점의 위치
int count, // 찾으려는 점의 갯수
CvSize win_size, // 탐색 윈도우의 크기
int level, // 피라미드의 레벨 지정
char* status, // status=1:이동된 위치를 찾은 경우, status=0:이동된 위치를 찾지 못한 경우
float* track_error, // NULL
CvTermCriteria criteria, // 종료조건
int flags); // CV_LKFLOW_INITIAL_GUESSES 등
*** Line Fitting (polar 코디네이트가 아니라 단점 있음)
int count = 0; // total number of points
float *line;
CvPoint left, right;
//CvMat point_mat = cvMat( 1, count, CV_32SC2, mid_points );
//cvFitLine( &point_mat, CV_DIST_L2 , 0, // line[0]:vector_x, line[1]:vector_y
// 0.01, 0.01, line ); // line[2]:x_n, line[3]:y_n
//
long double a, b, c, d, e, f;
////b가 기울기, a가 절편
//b = line[1]/ line[0];
//a = line[3]- b*line[2];
b=((float)right.y-(float)left.y)/((float)right.x-(float)right.y);
//left.x=mid_points[0].x;
//left.y=b*left.x+a;
//right.x=mid_points[count-1].x;
//right.y=b*right.x+a;
//CvPoint center;
//center.x = line[2];
//center.y = line[3]; // can draw from left to right directly
//cvLine( processed_image, center, left, CV_RGB(255,255,255), 1, 8 );
cvLine( Draw_results, left, right, CV_RGB(255,0,0), 1, 8 );
*** Mean-Shift Segmentation
//입출력 IplImage, spatial과 color radius 매개변수, level of scale pyramid(2 또는 3 적당)
cvPyrMeanShiftFiltering(src_color, src_result, 2, 40, 3);
*** 체스보드 마크 탐지하기
int i;
int nCornerNum = 3 * 3; // number of corners in the chessboard (3 * 3)
int MAX_COUNT = nCornerNum; // 5000
CvSize pattern_size = cvSize( COL_CHESS_CORNER_NUM, ROW_CHESS_CORNER_NUM );
CvPoint2D32f *left_corners = new CvPoint2D32f[nCornerNum];
CvPoint2D32f *right_corners = new CvPoint2D32f[nCornerNum];
int iLeft_corner_count, iRight_corner_count;
// Get the number of left and right corners
int iFoundLeft = cvFindChessboardCorners(pLeftImg, pattern_size, left_corners, &iLeft_corner_count, CV_CALIB_CB_ADAPTIVE_THRESH);
int iFoundRight = cvFindChessboardCorners(pRightImg, pattern_size, right_corners, &iRight_corner_count, CV_CALIB_CB_ADAPTIVE_THRESH);
//////////////////////////////////////////////////////////////////////////
//printf("\n-------------- Marker Results -----------------------------\n");
//printf("Number of Left Corners: %d\n", iLeft_corner_count);
cvDrawChessboardCorners(pLeftImg, pattern_size, left_corners, iLeft_corner_count, iFoundLeft);
cvDrawChessboardCorners(pRightImg, pattern_size, right_corners, iRight_corner_count, iFoundRight);
/*
for (i = 0; i < iLeft_corner_count; i++)
{
DrawCorner(pLeftImg, cvPointFrom32f(left_corners[i]));
//printf("(%d,%d)\t", cvPointFrom32f(left_corners[i]).x, cvPointFrom32f(left_corners[i]).y);
}
*/
//printf("\nNumber of right Corners: %d\n", iRight_corner_count);
//for(i=0; i<iRight_corner_count; i++)
//{
// DrawCorner(pRightImg, cvPointFrom32f(right_corners[i]));
// //printf("(%d,%d)\t", cvPointFrom32f(right_corners[i]).x, cvPointFrom32f(right_corners[i]).y);
//}
float *plane = new float[4]; // return value
for (i=0; i<4; i++) // Initialization, even though the plane equation is wrong
{
plane[i] = 1;
}
// Calculate the plane equation based on the chessboard
if( iLeft_corner_count == iRight_corner_count && iLeft_corner_count == nCornerNum) // Left Corners and right corners should be same
{
CvPoint *leftPoints = new CvPoint[nCornerNum];
CvPoint *rightPoints = new CvPoint[nCornerNum];
for(i=0; i<nCornerNum; i++)
{
leftPoints[i] = cvPointFrom32f(left_corners[i]);
rightPoints[i] = cvPointFrom32f(right_corners[i]);
}
plane = planeEquationfrom2DPoints(leftPoints, rightPoints, nCornerNum, baseLine, focal, u0, v0);
// output the plane equation result
printf("\n------------------------- Plane Equation ------------------------\n");
for(i=0; i<4; i++)
{
printf("%.4f\t", plane[i]);
}
printf("\n");
//----------------------------------------------------------
delete [] leftPoints;
delete [] rightPoints;
}
else
printf("No Enough Corners For Marker \n"); // should modify
//if (left_corners)
// cvFree(&left_corners);
//if (right_corners)
// cvFree(&right_corners);
if (left_corners)
delete [] left_corners;
if (right_corners)
delete [] right_corners;
return plane;
*** 히스토그램 평활화 (histogram equalization)
IplImage* Src = cvCreateImage(cvSize(width,height), 8, 1); //원본 이미지
IplImage* Equalized = cvCreateImage(cvSize(width,height), 8, 1); //평활화 된 이미지
cvEqualizeHist( Src, Equalized );
*** OpenCV 외 유용한 코드들
//파일에서 불러오기
FILE *fp = fopen(".\img.txt", "r");
if(fp == NULL)
return false;
while (fgets(buffer,BUFFERSIZE,fp))
{
label = strtok(buffer,ct);
if(label == NULL)
continue;
pDPT[p_index*NUMOFDIMESION] = (float)atof(label);
pDPT[p_index*NUMOFDIMESION + 1] = (float)atof(strtok(NULL,ct));
pDPT[p_index*NUMOFDIMESION + 2] = (float)atof(strtok(NULL,ct));
pBGR[c_index*NUMOFDIMESION] = (unsigned char)atoi(strtok(NULL,ct));
pBGR[c_index*NUMOFDIMESION +1] = (unsigned char)atoi(strtok(NULL,ct));
pBGR[c_index*NUMOFDIMESION +2] = (unsigned char)atoi(strtok(NULL,ct));
pGray[c_index] = pBGR[c_index*NUMOFDIMESION];
strtok(NULL,ct);
strtok(NULL,ct);
temp = strtok(NULL,ct);
if(atoi(&temp[1]) <= 0)
{
// zero disparity or invalid 3D point
pDPT[p_index*NUMOFDIMESION] = INVALID_DEPTH_INFO;
pDPT[p_index*NUMOFDIMESION + 1] = INVALID_DEPTH_INFO;
pDPT[p_index*NUMOFDIMESION + 2] = INVALID_DEPTH_INFO;
}
p_index++;
c_index++;
}
fclose(fp);
//3D만 가져올 때
char buffer[1024];
char *label;
char ct [] = " ,\t\n";
int index=0;
FILE *fp = fopen(".\img.txt", "r");
if(fp == NULL)
return;
while (fgets(buffer,1024,fp))
{
label = strtok(buffer,ct);
if(label == NULL)
continue;
p_3Dpt[index*3 ] = (float)atof(label);
p_3Dpt[index*3 + 1] = (float)atof(strtok(NULL,ct));
p_3Dpt[index*3 + 2] = (float)atof(strtok(NULL,ct));
index++;
if(index>=307200)
break;
}
fclose(fp);
//메모리, 용량 절약형 가져올 때
FILE *fp;
fp = fopen(file_name,"rt");
if(!fp)
{
printf("\ncan not open 3dmfile\n");
return false;
}
while (fgets(buffer,2000,fp))
{
label = strtok(buffer,ct);
if(label == NULL) continue;
if(!strcmp("ImageWidth",label))
{
//m_imagewidth = atoi(strtok(NULL,ct));///samplingratio;
}
else if(!strcmp("ImageHeight",label))
{
//m_imageheight = atoi(strtok(NULL,ct));///samplingratio;
}
else if(!strcmp("F",label))
{
double x,y;
double x3,y3,z3;
x = atof(strtok(NULL,ct));
y = atof(strtok(NULL,ct));
x3 = (double)atof(strtok(NULL,ct));
y3 = (double)atof(strtok(NULL,ct));
z3 = (double)atof(strtok(NULL,ct));
m_p3Dpt[3*(GetWidth() * (int)y + (int)x) ] = x3;
m_p3Dpt[3*(GetWidth() * (int)y + (int)x)+1] = y3;
m_p3Dpt[3*(GetWidth() * (int)y + (int)x)+2] = z3;
//y3 = -(double)atof(strtok(NULL,ct));
// SVS ver 3.2 used mm scale
//x3DPoints.push_back((float)x3*scale);
//y3DPoints.push_back((float)y3*scale);
//z3DPoints.push_back((float)z3*scale);
// SVS ver 4.4 use m scale (model is saved by using m scale)
//x3DPoints.push_back((float)x3);
//y3DPoints.push_back((float)y3);
//z3DPoints.push_back((float)z3);
//if(idxDB == WCCup) printf("\nx=%f,\ty=%f,\tz=%f",x3,y3,z3);
}
}
fclose(fp);
//파일로 저장하기
FILE *fp = fopen("@@_FilterResult.txt", "at+");
fprintf(fp, "%d %f\n", nFrameNum, pEstimatedObjectPose[11]);
fclose(fp);
//메모리 카피
memcpy(src_color->imageData, m_pColorImage, sizeof(unsigned char)*width*height*3);
//3D를 2D로 그리기 (대충)
for(int i=0;i<width;++i)
{
for(int j=0;j<height;++j)
{
if((m_p3Dpt[3*(i+width*j)+2]>0.5)&(m_p3Dpt[3*(i+width*j)+2]<2.0))
view_3D->imageData[i+width*j]=((m_p3Dpt[3*(i+width*j)+2]-0.5)/1.5)*255;
else
view_3D->imageData[i+width*j]=0;
}
}