본문 바로가기

Research/Math

공분산의 의미


(사진 출처 : http://www.wikihow.com/Calculate-Covariance)


covariance(공분산)의 의미는 x, y 가 존재할때, 이에 대한 상관관계를 의미한다. 예를 들어, x가 커지면 y도 커질까?


covar =   dxx   dxy

       dxy  dyy


즉, dx, dy, dxy 3개의 값을 구하면된다.


이제부터,

dxx = sum((x-mean_x)^2)/N

dyy = sum((y-mean_y)^2)/N

dxy = sum((x-mean_x)*(y-mean_y))/N


구할 수 있다.


그런데 더 의미를 찾으면, 우리는 여기에서 dxx, dyy, dxy 어디서 본것 같지 않나요??


즉, edge의 방향 성분과 유사하며, 이는 곧 분포도에 대한 방향을 획득할 수 있다. (참고 -  pca의 eigenvector는 이런 축을 나타내는데 이와 연관있다고 할수 있다.)


즉, dxx가 강하면 수평방향, dyy가 강하면 수직방향, dxy가 강하면 대각성 방향성 크다. 다시 말해 그 데이터의 분포도를 대충(?)알 수 있다.


찾아보니 괜찮은 블로그가 있네요. 링크

이 내용에서 보면 데이터의 분포도에 대한 정보에 대한 source가 있습니다.


void DrawProbDistribution (CDC &dc, int offset_x, int offset_y, dMatrix &C)
{
	// Draw a probability distribution
	// wikipedia에서 Multivariate normal distribution 참조
	dMatrix Cinv = !C;
	for (double x=-100; x<100; x+=1) {
		for (double y=-100; y<100; y+=1) {
			/*
			dMatrix v(2,1);
			v(0,0) = x;
			v(1,0) = y;
			dMatrix e = ~v*Cinv*v;
			double p = exp(-0.5*e(0,0));
			*/
			//  주석 처리한 행렬 연산을 풀어쓰면 다음과 같다.
			double p = exp (-0.5*(x*x*Cinv(0,0) + 2*x*y*Cinv(0,1) + y*y*Cinv(1,1)));
			dc.SetPixel ((int)(offset_x + x), (int)(offset_y - y), RGB(255*p,0,0));
		}
	}
}
void DrawCovarianceEllipse_Rotat (CDC &dc, int offset_x, int offset_y, double sigma_xx, double sigma_yy, double sigma_xy)
{
	// Draw covariance ellipse
	// Derivation from Rotations
	// http://www.geom.unimelb.edu.au/nicole/surveynetworks/02a/notes09_01.html 참조
	double theta = 0.5*atan(2*sigma_xy/(sigma_yy - sigma_xx));
	double st = sin(theta);
	double ct = cos(theta);
	double a = sqrt(sigma_xx*ct*ct - 2*sigma_xy*st*ct + sigma_yy*st*st);
	double b = sqrt(sigma_xx*st*st + 2*sigma_xy*st*ct + sigma_yy*ct*ct);
	for (int i=0; i<=360; i+=10) {
		double ri = _DEG2RAD*i;
		double u = a*cos(ri);
		double v = b*sin(ri);
		double rx =  u*ct + v*st;
		double ry = -u*st + v*ct;
		if (i==0) dc.MoveTo ((int)(offset_x + rx), (int)(offset_y - ry));
		else      dc.LineTo ((int)(offset_x + rx), (int)(offset_y - ry));
	}
}
void DrawCovarianceEllipse_Eigen (CDC &dc, int offset_x, int offset_y, dMatrix &C)
{
	// Draw covariance ellipse
	// Derivation from Eigen value and vectors
	// Paul Michael Newman의 "C4B | Mobile Robotics"에서 Topic 10.1 Drawing Covariance Ellipses 참조
	dVector D;
	dMatrix V;
	if (C.eigen(D, V)) {
		for (unsigned int i = 0; i<D.size(); ++i) {
			D[i] = sqrt(D[i]);
		}
		for (int i=0; i<=360; i+=10) {
			double ri = _DEG2RAD*i;
			double x = D[0]*cos(ri);
			double y = D[1]*sin(ri);
			double rx = V(0,0)*x + V(0,1)*y;
			double ry = V(1,0)*x + V(1,1)*y;
			if (i==0) dc.MoveTo ((int)(offset_x + rx), (int)(offset_y - ry));
			else      dc.LineTo ((int)(offset_x + rx), (int)(offset_y - ry));
		}
	}

}


그리고 Covariance를 구한 소스 예는 

void cal_ovariance(,,,,,)

{

        int sx = roi.x, sy = roi.y;

        int ex = roi.x+roi.width, ey = roi.y+roi.height;

        if(sx<0) sx = 0; if(sy<0) sy = 0;

        if(ey>image->height) ey = image->height;

        if(ex>image->width)  ex = image->width;


        double sumR, sumC, sumRR, sumCC, sumRC, sumW;

        sumRR = sumCC = sumR = sumC = sumW = sumRC = 0.0;


        GIMAGE _image; // 입력 그레이 이미지

        for(int i=sy; i<ey; i++){

                for(int j=sx; j<ex; j++){

                        int val = _image[i][j];

                        int r = i*val;

                        int c = j*val;


                        sumW += val;

                        sumR += r;

                        sumC += c;


                        sumRR += r*i;

                        sumCC += c*j;

                        sumRC += val*i*j;

                }

        }

        meanX = sumC/sumW;

        meanY = sumR/sumW;

        double covRC = (sumRC/sumW)-(meanX*meanY);

      

        // 최종적으로,

        dxx  = (sumRR/sumW)-powf(meanY,2);

        dxy  = covRC;

        dyy = (sumCC/sumW)-powf(meanX,2);

}


'Research > Math' 카테고리의 다른 글

l0-Norm, l1-Norm, l2-Norm, … , l-infinity Norm  (0) 2014.12.17
orthogonal matrix = 직교  (0) 2014.04.25