제 6 장 영상 워핑과 모핑
학습목표 다음 기하학적 처리의 개념을 설명할 수 있고 프로그램을 작성할 수 있다 영상 워핑 영상 모핑 2018-11-11 영상처리
영상 워핑(Warping) 픽셀의 위치를 이동하는 기하학적 처리 회전, 이동, 확대/축소등의 기하학적 처리와의 차이점 픽셀 별로 이동 정도가 다름 고무종이 위에 그려진 영상을 임의로 구부리는 효과를 낼 수 있음 2018-11-11 영상처리
영상 워핑(Warping) 사용 예 인공 위성이나 우주선에서 보내온 일그러진 영상을 복원하는데 처음 사용 TV나 영화에서 물체, 동물, 배우의 모습을 변형하는 데 사용 미아의 성장 모습을 생성 2018-11-11 영상처리
영상 워핑 2018-11-11 영상처리
영상 워핑 입력 영상과 출력 영상의 대응관계 기술 제어선, 제어점, 그물망, 다각형 등 다양한 방법이 있음 <제어점> <제어선> 2018-11-11 영상처리
제어선을 이용한 워핑 출력 영상의 픽셀 V에 대응되는 입력 영상의 픽셀 V’을 찾아서 픽셀값 복사 수직 교차점이 제어선 내부에 존재 V’ 변위 P’ Q’ 위치 V P Q 출력 영상 입력 영상 C’ C 2018-11-11 영상처리
제어선을 이용한 워핑 수직 교차점이 제어선 외부에 존재 Q’ Q P’ P V’ C’ V C 입력 영상 출력 영상 위치 변위 2018-11-11 영상처리
제어선을 이용한 워핑 제어선이 여러 개인 경우 각 제어선에 대한 가중치 고려 제어선은 영상 내의 모든 화소들에 영향을 미침 p 가중치 = (a+픽셀과 제어선의 거리) 제어선의 길이 p b p : 선의 길이에 대한 가중치 (0 p 1) a : 0으로 나누는 것을 방지 b : 거리의 증가에 대한 가중치의 감소율 (0.5 b 2.0) 2018-11-11 영상처리
제어선을 이용한 영상 워핑 알고리즘 warping() { 출력 영상의 각 픽셀 V(x,y) 에 대하여 tx = 0 // 방향 변위의 합을 나타내는 변수를 초기화한다 ty = 0 // 방향 변위의 합을 나타내는 변수를 초기화한다 totalWeight = 0 // 가중치의 합을 나타내는 변수를 초기화한다 각 제어선 Li 에 대하여 V와 Li 의 수직교차점의 위치 u 를 계산한다. V와 Li 의 수직 변위 h 를 계산한다 u 와 h 를 이용하여 입력 영상에서의 대응 위치 V’(x’, y’)을 구한다. V와 Li 사이의 거리를 d 를 계산한다. weight = ((제어선의 길이p)/(a+d))b tx = tx + (x’-x) * weight ty = ty + (y’-y) * weight totalWeight = totalWeight + weight } X = x + tx / totalWeight Y = y + ty / totalWeight 입력 영상의 V’(X,Y) 픽셀의 값을 출력 영상의 V(x,y)픽셀에 복사한다. 2018-11-11 영상처리
제어선을 이용한 워핑 수직 교차점의 위치 계산 2018-11-11 영상처리
제어선을 이용한 워핑 수직 교차점의 위치 계산 u < 0 : P 바깥에 위치 u > 1 : Q 외부에 위치 2018-11-11 영상처리
(a) h > 0인 경우 (b) h < 0인 경우 제어선을 이용한 워핑 제어선으로부터의 변위 계산 픽셀을 지나면서 제어선과 수직으로 교차하는 점과 픽셀 사이의 변위 변위(h)의 값 변위 < 0 : 픽셀이 제어선 아래쪽에 있음 변위 = 0 : 픽셀이 제어선에 있음 변위 > 0 : 픽셀이 제어선 위쪽에 있음 (a) h > 0인 경우 (b) h < 0인 경우 2018-11-11 영상처리
제어선을 이용한 워핑 제어선으로부터의 변위 계산 2018-11-11 영상처리
제어선을 이용한 워핑 입력 영상에서 대응 픽셀 위치 계산 : 제어선 Li의 양 끝점 좌표 2018-11-11 영상처리
제어선을 이용한 워핑 픽셀과 제어선의 거리 계산 Q Q V P Q V P P V (b) 수직 교차점이 제어선 외부에 있는 경우 d Q d d V P P V 수직 교차점이 제어선 내부에 있는 경우 (b) 수직 교차점이 제어선 외부에 있는 경우 2018-11-11 영상처리
제어선을 이용한 워핑 픽셀과 제어선 사이의 거리 계산 P Q V d 2018-11-11 영상처리
제어선을 이용한 워핑 제어선의 가중치 계산 2018-11-11 영상처리
제어선을 이용한 워핑 입력 영상 대응 픽셀의 변위 누적 2018-11-11 영상처리
제어선을 이용한 워핑 입력 영상의 대응 픽셀 위치 계산 2018-11-11 영상처리
모핑(Morphing) 두 개의 서로 다른 입력 영상에 대하여 한 영상을 다른 영상으로 변환 2018-11-11 영상처리
모핑의 단계 모핑은 워핑과 합병의 두 단계로 구성 2018-11-11 영상처리
두 영상 사이의 대응 관계 기술 모핑을 위해서는 두 영상 사이의 대응 위치를 기술해야 함 2018-11-11 영상처리
워핑 중간 프레임에 대한 제어선 생성 두 입력 영상의 제어선으로부터 보간법을 사용하여 생성 2018-11-11 영상처리
워핑 K번째 중간 프레임에 대한 제어선 계산 식 N : 전체 프레임 수 2018-11-11 영상처리
합병 영상 합병 I1(x,y) : 입력 영상 1로부터 복사되는 픽셀 값 I2(x,y) : 입력 영상 2로부터 복사되는 픽셀 값 2018-11-11 영상처리
실습
워핑 기하학적 처리 메뉴에 워핑 연산 부메뉴 추가 이름 : 워핑 ID : ID_GEOMETRY_WARPING
워핑 CImageProView 클래스에 OnGeometryWarping() 함수를 추가하고 편집한다. void CImageProView::OnGeometryWarping() { CImageProDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (pDoc->inputImg == NULL) return; pDoc->GeometryWarping(); viewMode = TWO_IMAGES; Invalidate(FALSE); }
워핑 CImageProDoc 클래스에 GeometryWarping() 함수를 추가 반환 형식: void
워핑 typedef struct { int Px; int Py; int Qx; int Qy; } control_line; #include <math.h> void CImageProDoc::GeometryWarping() control_line source_lines[23] = {{116,7,207,5},{34,109,90,21},{55,249,30,128},{118,320,65,261}, {123,321,171,321},{179,319,240,264},{247,251,282,135},{281,114,228,8}, {78,106,123,109},{187,115,235,114},{72,142,99,128},{74,150,122,154}, {108,127,123,146},{182,152,213,132},{183,159,229,157},{219,131,240,154}, {80,246,117,212},{127,222,146,223},{154,227,174,221},{228,252,183,213}, {114,255,186,257},{109,258,143,277},{152,278,190,262}};
워핑 control_line dest_lines[23] = {{120,8,200,6},{12,93,96,16},{74,271,16,110},{126,336,96,290}, {142,337,181,335},{192,335,232,280},{244,259,288,108},{285,92,212,13}, {96,135,136,118},{194,119,223,125},{105,145,124,134},{110,146,138,151}, {131,133,139,146},{188,146,198,134},{189,153,218,146},{204,133,221,140}, {91,268,122,202},{149,206,159,209},{170,209,181,204},{235,265,208,199}, {121,280,205,284},{112,286,160,301},{166,301,214,287}}; double u; // 수직 교차점의 위치 double h; // 제어선으로부터 픽셀의 수직 변위 double d; // 제어선과 픽셀 사이의 거리 double tx, ty; // 결과영상 픽셀에 대응되는 입력 영상 픽셀 사이의 변위의 합 double xp, yp; // 각 제어선에 대해 계산된 입력 영상의 대응되는 픽셀 위치 double weight; // 각 제어선의 가중치 double totalWeight; // 가중치의 합 double a=0.001; double b=2.0; double p=0.75;
워핑 int x1, x2, y1, y2; int src_x1, src_y1, src_x2, src_y2; double src_line_length, dest_line_length; int num_lines = 23; // 제어선의 수 int line; int x, y; int source_x, source_y; int last_row, last_col; last_row = imageHeight-1; last_col = imageWidth-1;
워핑 // 출력 영상의 각 픽셀에 대하여 for(y=0; y<imageHeight; y++) { for(x=0; x<imageWidth; x++) totalWeight = 0.0; tx = 0.0; ty = 0.0; // 각 제어선에 대하여 for (line = 0; line < num_lines; line++) x1 = dest_lines[line].Px; y1 = dest_lines[line].Py; x2 = dest_lines[line].Qx; y2 = dest_lines[line].Qy; dest_line_length = sqrt((double) (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
워핑 // 수직교차점의 위치 및 픽셀의 수직 변위 계산 u = (double) ((x-x1)*(x2-x1)+(y-y1)*(y2-y1)) / (double) ((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); h = (double) ((y-y1)*(x2-x1)-(x-x1)*(y2-y1)) / dest_line_length; // 제어선과 픽셀 사이의 거리 계산 if (u < 0 ) d = sqrt((double) (x-x1) * (x-x1) + (y-y1) * (y-y1)); else if (u > 1) d = sqrt((double) (x-x2) * (x-x2) + (y-y2) * (y-y2)); else d = fabs(h); src_x1 = source_lines[line].Px; src_y1 = source_lines[line].Py; src_x2 = source_lines[line].Qx; src_y2 = source_lines[line].Qy; src_line_length=sqrt((double) (src_x2-src_x1)*(src_x2-src_x1)+ (src_y2-src_y1)*(src_y2-src_y1));
워핑 // 입력 영상에서의 대응 픽셀 위치 계산 xp = src_x1+u*(src_x2 - src_x1) - h * (src_y2 - src_y1) / src_line_length; yp = src_y1+u*(src_y2 - src_y1) + h * (src_x2 - src_x1) / src_line_length; // 제어선에 대한 가중치 계산 weight = pow((pow((double)(dest_line_length),p) / (a + d)) , b); // 대응 픽셀과의 변위 계산 tx += (xp - x) * weight; ty += (yp - y) * weight; totalWeight += weight; }
워핑 source_x = x + (int) (tx / totalWeight + 0.5); source_y = y + (int) (ty / totalWeight + 0.5); // 영상의 경계를 벗어나는지 검사 if (source_x < 0) source_x = 0; if (source_x > last_col) source_x = last_col; if (source_y < 0) source_y = 0; if (source_y > last_row) source_y = last_row; resultImg[y][x] = inputImg[source_y][source_x]; }
워핑 Warp.pgm 파일을 열어서 워핑을 적용
모핑 기하학적 처리 메뉴에 모핑 부메뉴 추가 Caption : 모핑 ID : ID_GEOMETRY_MORPHING
모핑 CImageProView 클래스에 OnGeometryMorphing() 함수 추가 void CImageProView::OnGeometryMorphing() { CImageProDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pDoc->GeometryMorphing(); viewMode = MORPHING; Invalidate(FALSE); }
모핑 CImageProView.cpp 파일의 위부분에 MORPHING 상수에 대한 정의를 추가 -- 추가하기전 #define TWO_IMAGES 1 #define THREE_IMAGES 2 #define TWO_IMAGES_SCALED 4 -- 추가한 다음 #define MORPHING 8
모핑 CImageProDoc 클래스의 정의에 모핑 과정에서 생성되는 중간 프레임을 저장하기 위한 변수 morphedImg를 선언 // Attributes public: unsigned char **inputImg; // 입력 영상의 기억 장소에 대한 포인터 변수 unsigned char **inputImg2; // 입력 영상의 기억 장소에 대한 포인터 변수 unsigned char **resultImg; // 출력 영상의 기억 장소에 대한 포인터 변수 int imageWidth; // 영상의 가로 크기 int imageHeight; // 영상의 세로 크기 int depth; // 1 = 흑백 영상, 3 = 컬러 영상 int gImageWidth; // 크기가 변한 결과 영상의 가로 크기 int gImageHeight; // 크기가 변한 결과 영상의 세로 크기 unsigned char **gResultImg; // 크기가 변한 결과 영상에 대한 포인터 변수 // 모핑 결과 저장을 위해 새로이 추가되는 코드 unsigned char **morphedImg[10];
모핑 CImageProDoc 클래스에 GeometryMorphing() 함수를 추가 반환 형식: void
모핑 #define NUM_FRAMES 10 void CImageProDoc::GeometryMorphing() { control_line source_lines[23] = {{116,7,207,5},{34,109,90,21},{55,249,30,128},{118,320,65,261}, {123,321,171,321},{179,319,240,264},{247,251,282,135},{281,114,228,8}, {78,106,123,109},{187,115,235,114},{72,142,99,128},{74,150,122,154}, {108,127,123,146},{182,152,213,132},{183,159,229,157},{219,131,240,154}, {80,246,117,212},{127,222,146,223},{154,227,174,221},{228,252,183,213}, {114,255,186,257},{109,258,143,277},{152,278,190,262}}; control_line dest_lines[23] = {{120,8,200,6},{12,93,96,16},{74,271,16,110},{126,336,96,290}, {142,337,181,335},{192,335,232,280},{244,259,288,108},{285,92,212,13}, {96,135,136,118},{194,119,223,125},{105,145,124,134},{110,146,138,151}, {131,133,139,146},{188,146,198,134},{189,153,218,146},{204,133,221,140}, {91,268,122,202},{149,206,159,209},{170,209,181,204},{235,265,208,199}, {121,280,205,284},{112,286,160,301},{166,301,214,287}};
모핑 double u; // 수직 교차점의 위치 double h; // 제어선으로부터 픽셀의 수직 변위 double d; // 제어선과 픽셀 사이의 거리 double tx, ty; // 결과영상 픽셀에 대응되는 입력 영상 픽셀 사이의 변위의 합 double xp, yp; // 각 제어선에 대해 계산된 입력 영상의 대응되는 픽셀 위치 double weight; // 각 제어선의 가중치 double totalWeight; // 가중치의 합 double a=0.001, b=2.0, p=0.75; unsigned char **warpedImg; unsigned char **warpedImg2; int frame; double fweight; control_line warp_lines[23]; double tx2, ty2, xp2, yp2; int dest_x1, dest_y1, dest_x2, dest_y2, source_x2, source_y2; int x1, x2, y1, y2, src_x1, src_y1, src_x2, src_y2; double src_line_length, dest_line_length; int i, j; int num_lines = 23; // 제어선의 수 int line, x, y, source_x, source_y, last_row, last_col;
모핑 // 두 입력 영상을 읽어들임 LoadTwoImages(); // 중간 프레임의 워핑 결과를 저장을 위한 기억장소 할당 warpedImg = (unsigned char **) malloc(imageHeight * sizeof(unsigned char *)); for (i = 0; i < imageHeight; i++) { warpedImg[i] = (unsigned char *) malloc(imageWidth * depth); } warpedImg2 = (unsigned char **) malloc(imageHeight * sizeof(unsigned char *)); warpedImg2[i] = (unsigned char *) malloc(imageWidth * depth);
모핑 for (i = 0; i < NUM_FRAMES; i++) { morphedImg[i]=(unsigned char **) malloc(imageHeight*sizeof(unsigned char *)); for (j = 0; j < imageHeight; j++) { morphedImg[i][j] = (unsigned char *) malloc(imageWidth * depth); } last_row = imageHeight-1; last_col = imageWidth-1;
모핑 // 각 중간 프레임에 대하여 for(frame=1; frame <= NUM_FRAMES; frame++) { // 중간 프레임에 대한 가중치 계산 fweight = (double)(frame) / NUM_FRAMES; // 중간 프레임에 대한 제어선 계산 for(line=0; line<num_lines; line++) warp_lines[line].Px = (int) (source_lines[line].Px + (dest_lines[line].Px - source_lines[line].Px)*fweight); warp_lines[line].Py =(int) (source_lines[line].Py + (dest_lines[line].Py - source_lines[line].Py)*fweight); warp_lines[line].Qx = (int) (source_lines[line].Qx + (dest_lines[line].Qx - source_lines[line].Qx)*fweight); warp_lines[line].Qy = (int) (source_lines[line].Qy + (dest_lines[line].Qy - source_lines[line].Qy)*fweight); }
모핑 // 출력 영상의 각 픽셀에 대하여 for(y=0; y<imageHeight; y++) { for(x=0; x<imageWidth; x++) totalWeight = 0.0; tx = 0.0; ty = 0.0; tx2 = 0.0; ty2 = 0.0; // 각 제어선에 대하여 for (line = 0; line < num_lines; line++) x1 = warp_lines[line].Px; y1 = warp_lines[line].Py; x2 = warp_lines[line].Qx; y2 = warp_lines[line].Qy; dest_line_length = sqrt((double) (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
모핑 // 수직교차점의 위치 및 픽셀의 수직 변위 계산 u = (double) ((x-x1)*(x2-x1)+(y-y1)*(y2-y1))/ (double) ((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); h = (double) ((y-y1)*(x2-x1)-(x-x1)*(y2-y1))/ dest_line_length; // 제어선과 픽셀 사이의 거리 계산 if (u < 0 ) d = sqrt((double) (x-x1) * (x-x1) + (y-y1) * (y-y1)); else if (u > 1) d = sqrt((double) (x-x2) * (x-x2) + (y-y2) * (y-y2)); else d = fabs(h); src_x1 = source_lines[line].Px; src_y1 = source_lines[line].Py; src_x2 = source_lines[line].Qx; src_y2 = source_lines[line].Qy; src_line_length = sqrt((double) (src_x2-src_x1)*(src_x2-src_x1) + (src_y2-src_y1)*(src_y2-src_y1));
모핑 dest_x1 = dest_lines[line].Px; dest_y1 = dest_lines[line].Py; dest_x2 = dest_lines[line].Qx; dest_y2 = dest_lines[line].Qy; dest_line_length = sqrt((double) (dest_x2-dest_x1)*(dest_x2-dest_x1) + (dest_y2-dest_y1)*(dest_y2-dest_y1)); // 입력 영상 1에서의 대응 픽셀 위치 계산 xp = src_x1 + u * (src_x2 - src_x1) - h * (src_y2 - src_y1) / src_line_length; yp = src_y1 + u * (src_y2 - src_y1) + h * (src_x2 - src_x1) / src_line_length; // 입력 영상 2에서의 대응 픽셀 위치 계산 xp2 = dest_x1 + u * (dest_x2 - dest_x1) - h * (dest_y2 - dest_y1) / dest_line_length; yp2 = dest_y1 + u * (dest_y2 - dest_y1) + h * (dest_x2 - dest_x1) / dest_line_length;
모핑 // 제어선에 대한 가중치 계산 weight = pow((pow((double)(dest_line_length),p) / (a + d)) , b); // 입력 영상 1의 대응 픽셀과의 변위 계산 tx += (xp - x) * weight; ty += (yp - y) * weight; // 입력 영상 2의 대응 픽셀과의 변위 계산 tx2 += (xp2 - x) * weight; ty2 += (yp2 - y) * weight; totalWeight += weight; }
모핑 // 입력 영상 1의 대응 픽셀 위치 계산 source_x = x + (int) (tx / totalWeight + 0.5); source_y = y + (int) (ty / totalWeight + 0.5); // 입력 영상 2의 대응 픽셀 위치 계산 source_x2 = x + (int) (tx2 / totalWeight + 0.5); source_y2 = y + (int) (ty2 / totalWeight + 0.5); // 영상의 경계를 벗어나는지 검사 if (source_x < 0) source_x = 0; if (source_x > last_col) source_x = last_col; if (source_y < 0) source_y = 0; if (source_y > last_row) source_y = last_row; if (source_x2 < 0) source_x2 = 0; if (source_x2 > last_col) source_x2 = last_col; if (source_y2 < 0) source_y2 = 0; if (source_y2 > last_row) source_y2 = last_row;
모핑 // 워핑 결과 저장 warpedImg[y][x] = inputImg[source_y][source_x]; } // 모핑 결과 합병 for(y=0; y<imageHeight; y++) for(x=0; x<imageWidth; x++) { int val = (int) ((1.0 - fweight) * warpedImg[y][x] + fweight * warpedImg2[y][x]); if (val < 0) val = 0; if (val > 255) val = 255; morphedImg[frame-1][y][x] = val;
모핑 OnDraw() 함수를 수정 void CImageProView::OnDraw(CDC* pDC) { CImageProDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (pDoc->inputImg == NULL) return; if (pDoc->depth == 1) { for(int y=0; y < pDoc->imageHeight; y++) // 입력 영상 출력 for(int x=0; x < pDoc->imageWidth; x++) pDC->SetPixel(x, y, RGB(pDoc->inputImg[y][x], pDoc->inputImg[y][x], pDoc->inputImg[y][x]));
모핑 if (viewMode == THREE_IMAGES) { for(int y=0; y< pDoc->imageHeight; y++) // 두번째 입력 영상 출력 for(int x=0; x< pDoc->imageWidth; x++) pDC->SetPixel(x+pDoc->imageWidth+30, y, RGB(pDoc->inputImg2[y][x], pDoc->inputImg2[y][x], pDoc->inputImg2[y][x])); for(int y=0; y< pDoc->imageHeight; y++) // 결과 영상 출력 pDC->SetPixel(x+pDoc->imageWidth*2+60, y, RGB(pDoc->resultImg[y][x], pDoc->resultImg[y][x], pDoc->resultImg[y][x])); }
모핑 else if (viewMode == TWO_IMAGES_SCALED) { for(int y=0; y< pDoc->gImageHeight; y++) // 크기가 변한 결과 영상 출력 for(int x=0; x< pDoc->gImageWidth; x++) pDC->SetPixel(x+pDoc->imageWidth+30, y, RGB(pDoc->gResultImg[y][x], pDoc->gResultImg[y][x], pDoc->gResultImg[y][x])); }
모핑 else if (viewMode == MORPHING) { for(int y=0; y< pDoc->imageHeight; y++) // 두번째 입력 영상 출력 for(int x=0; x< pDoc->imageWidth; x++) pDC->SetPixel(x+pDoc->imageWidth+30, y, RGB(pDoc->inputImg2[y][x], pDoc->inputImg2[y][x], pDoc->inputImg2[y][x])); for (int i = 0; i < 10; i++) for(int y=0; y< pDoc->imageHeight; y++) // 모핑 결과 출력 pDC->SetPixel(x+pDoc->imageWidth*2+60,y, RGB(pDoc->morphedImg[i][y][x], pDoc->morphedImg[i][y][x], pDoc->morphedImg[i][y][x])); }
모핑 else { for(int y=0; y< pDoc->imageHeight; y++) // 결과 영상 출력 for(int x=0; x< pDoc->imageWidth; x++) pDC->SetPixel(x+pDoc->imageWidth+30, y, RGB(pDoc->resultImg[y][x], pDoc->resultImg[y][x], pDoc->resultImg[y][x])); } else if (pDoc->depth == 3) { for(int y=0; y < pDoc->imageHeight; y++) // 입력 영상 출력 for(int x=0; x < pDoc->imageWidth; x++) pDC->SetPixel(x, y, RGB(pDoc->inputImg[y][3*x], pDoc->inputImg[y][3*x+1], pDoc->inputImg[y][3*x+2]));
모핑 if (viewMode == THREE_IMAGES) { for(int y=0; y< pDoc->imageHeight; y++) // 두번째 입력 영상 출력 for(int x=0; x< pDoc->imageWidth; x++) pDC->SetPixel(x+pDoc->imageWidth+30, y, RGB(pDoc->inputImg2[y][3*x], pDoc->inputImg2[y][3*x+1], pDoc->inputImg2[y][3*x+2])); for(int y=0; y< pDoc->imageHeight; y++) // 결과 영상 출력 pDC->SetPixel(x+pDoc->imageWidth*2+60, y, RGB(pDoc->resultImg[y][3*x], pDoc->resultImg[y][3*x+1], pDoc->resultImg[y][3*x+2])); }
모핑 else if (viewMode == TWO_IMAGES_SCALED) { for(int y=0; y< pDoc->gImageHeight; y++) // 크기가 변한 결과 영상 출력 for(int x=0; x< pDoc->gImageWidth; x++) pDC->SetPixel(x+pDoc->imageWidth+30, y, RGB(pDoc->gResultImg[y][3*x], pDoc->gResultImg[y][3*x+1], pDoc->gResultImg[y][3*x+2])); } else { for(int y=0; y< pDoc->imageHeight; y++) // 결과 영상 출력 for(int x=0; x< pDoc->imageWidth; x++) RGB(pDoc->resultImg[y][3*x], pDoc->resultImg[y][3*x+1], pDoc->resultImg[y][3*x+2]));
모핑 프로그램을 컴파일하고 모핑 실행 두 입력 영상 선택 첫번째 : "morph_src.pgm“, 두번째 : “morph_dest.pgm"