積分画像と積分ヒストグラム


転載:(本文の所有権は原作者が所有する)
http://blog.csdn.net/zhazhiqiang/article/details/18769195
http://blog.sina.com.cn/s/blog_679 e 132901 cph.
******************************************************************
積分ヒストグラムは、CVPR-2005の「Integral Higogram:A Fast Way to Extract Higograms in Catesian Spaces」の論文でFatih Porikliが記載されています.
    積分ヒストグラムを紹介する前に、積分画像を紹介します.積分画像はP.Viola and M.Jones「Robust real-time face dection」(ICCV 2001)で述べられています.
一、ポイント画像
    一枚の階調の画像に対して、積分画像のいずれかの点(x,y)の値は、画像の左上からこの点までの矩形領域内の全ての点の階調値の合計である.
积分直方图(Integral <wbr>Histogram)
    実際の計算過程では、点(x,y)に対する値は以下の通りである.
I(x,y)=I(x-1,y)+I(y-1,x)-I(x-1,y-1)+G(i,j) (I:この点の積分画像値、G:この点の階調値)
    実際のプログラミングの実現過程では、画像のサイズを拡張し、左の列を拡張し、上の行を拡張します.
つまり、I(-1,j)=0,I(i,-1)=0となります.
    上記の計算が完了すると、画像内の任意の矩形枠の内点の階調数と、
积分图像与积分直方图_第1张图片
二、積分のヒストグラム
    積分画像と同様に、統計の領域はすべての画素点の階調和ではなく、この領域内の全ての画素のヒストグラムであり、例えば、画像の左上隅の始点から画像の右下隅まで統計するのがこの画像のヒストグラムであり、上の図に示すように、原点OとD点からなる矩形領域のヒストグラムである.
******************************************************************
方向勾配ヒストグラム(Higograms of Oriented Graadients、HOG特徴と略称する)
サポートベクトルマシン(support vector machine、略称SVM)を組み合わせて、画像認識に広く応用されています.特に歩行者検出において大きな成功を収めました. 積分ヒストグラムは、元の画像の矩形領域内のHOG特徴を迅速に計算するために使用できます.積分ヒストグラムの概念は、violaおよびjnesの顔認識に用いる積分画像と類似しています. 以下のコードは、与えられた画像に対して、積分ヒストグラムをどのように迅速に計算するかと、HOG特徴の演算をどのように行うかということを示しています.
/*Function to calculate the integral histogram*/  
IplImage** calculateIntegralHOG(IplImage* in)  
{  
    /*Convert the input image to grayscale*/  
    IplImage* img_gray = cvCreateImage(cvGetSize(in), IPL_DEPTH_8U,1);  
    cvCvtColor(in, img_gray, CV_BGR2GRAY);  
    cvEqualizeHist(img_gray,img_gray);  
  
/*Calculate the derivates of the grayscale image in the x and y directions using a sobel operator and obtain 2 gradient images for the x and y directions*/  
  
    IplImage *xsobel, *ysobel;  
    xsobel = doSobel(img_gray, 1, 0, 3);  
    ysobel = doSobel(img_gray, 0, 1, 3);  
    cvReleaseImage(&img_gray);  
  
  
/* Create an array of 9 images (9 because I assume bin size 20 degrees and unsigned gradient ( 180/20 = 9), one for each bin which will have zeroes for all pixels, except for the pixels in the original image for which the gradient values correspond to the particular bin. These will be referred to as bin images. These bin images will be then used to calculate the integral histogram, which will quicken the calculation of HOG descriptors */  
  
    IplImage** bins = (IplImage**) malloc(9 * sizeof(IplImage*));  
    for (int i = 0; i < 9 ; i++) {  
        bins[i] = cvCreateImage(cvGetSize(in), IPL_DEPTH_32F,1);  
        cvSetZero(bins);  
    }  
  
  
/* Create an array of 9 images ( note the dimensions of the image, the cvIntegral() function requires the size to be that), to store the integral images calculated from the above bin images. These 9 integral images together constitute the integral histogram */  
  
    IplImage** integrals = (IplImage**) malloc(9 * sizeof(IplImage*));   
    for (int i = 0; i < 9 ; i++) {  
        integrals[i] = cvCreateImage(cvSize(in->width + 1, in->height + 1),  
        IPL_DEPTH_64F,1);  
    }  
  
/* Calculate the bin images. The magnitude and orientation of the gradient at each pixel is calculated using the xsobel and ysobel images.{Magnitude = sqrt(sq(xsobel) + sq(ysobel) ), gradient = itan (ysobel/xsobel) }. Then according to the orientation of the gradient, the value of the corresponding pixel in the corresponding image is set */  
  
    int x, y;  
    float temp_gradient, temp_magnitude;  
    for (y = 0; y < in->height; y++) {  
  
/* ptr1 and ptr2 point to beginning of the current row in the xsobel and ysobel images respectively. ptrs point to the beginning of the current rows in the bin images */  
  
        float* ptr1 = (float*) (xsobel->imageData + y * (xsobel->widthStep));  
        float* ptr2 = (float*) (ysobel->imageData + y * (ysobel->widthStep));  
        float** ptrs = (float**) malloc(9 * sizeof(float*));  
        for (int i = 0; i < 9 ;i++){  
            ptrs[i] = (float*) (bins[i]->imageData + y * (bins->widthStep));  
        }  
  
/*For every pixel in a row gradient orientation and magnitude are calculated and corresponding values set for the bin images. */  
  
        for (x = 0; x <in->width; x++) {  
  
/* if the xsobel derivative is zero for a pixel, a small value is added to it, to avoid division by zero. atan returns values in radians, which on being converted to degrees, correspond to values between -90 and 90 degrees. 90 is added to each orientation, to shift the orientation values range from {-90-90} to {0-180}. This is just a matter of convention. {-90-90} values can also be used for the calculation. */  
  
            if (ptr1[x] == 0){  
                temp_gradient = ((atan(ptr2[x] / (ptr1[x] + 0.00001))) * (180/   PI)) + 90;  
            }  
            else{  
                temp_gradient = ((atan(ptr2[x] / ptr1[x])) * (180 / PI)) + 90;  
            }  
            temp_magnitude = sqrt((ptr1[x] * ptr1[x]) + (ptr2[x] * ptr2[x]));  
  
/*The bin image is selected according to the gradient values. The corresponding pixel value is made equal to the gradient magnitude at that pixel in the corresponding bin image */  
  
            if (temp_gradient <= 20) {  
                ptrs[0][x] = temp_magnitude;  
            }  
            else if (temp_gradient <= 40) {  
                ptrs[1][x] = temp_magnitude;  
            }  
            else if (temp_gradient <= 60) {  
                ptrs[2][x] = temp_magnitude;  
            }  
            else if (temp_gradient <= 80) {  
                ptrs[3][x] = temp_magnitude;  
            }  
            else if (temp_gradient <= 100) {  
                ptrs[4][x] = temp_magnitude;  
            }  
            else if (temp_gradient <= 120) {  
                ptrs[5][x] = temp_magnitude;  
            }  
            else if (temp_gradient <= 140) {  
                ptrs[6][x] = temp_magnitude;  
            }  
            else if (temp_gradient <= 160) {  
                ptrs[7][x] = temp_magnitude;  
            }  
            else {  
                ptrs[8][x] = temp_magnitude;  
            }  
        }  
    }  
  
    cvReleaseImage(&xsobel);  
    cvReleaseImage(&ysobel);  
  
/*Integral images for each of the bin images are calculated*/  
  
    for (int i = 0; i <9 ; i++){  
        cvIntegral(bins[i], integrals[i]);  
    }  
  
    for (int i = 0; i <9 ; i++){  
        cvReleaseImage(&bins[i]);  
    }  
  
/*The function returns an array of 9 images which consitute the integral histogram*/  
  
    return (integrals);  
  
}  
上記の関数を使って、9次元の方向勾配ヒストグラムを計算するにはどうすればいいですか?
/* The following function takes as input the rectangular cell for which the histogram of oriented gradients has to be calculated, a matrix hog_cell of dimensions 1x9 to store the bin values for the histogram, the integral histogram, and the normalization scheme to be used. No normalization is done if normalization = -1 */  
  
void calculateHOG_rect(CvRect cell, CvMat* hog_cell,  
IplImage** integrals, int normalization) {  
  
/* Calculate the bin values for each of the bin of the histogram one by one */  
  
    for (int i = 0; i < 9 ; i++){  
  
        float a =((double*)(integrals[i]->imageData + (cell.y) * (integrals->  
            widthStep)))[cell.x];  
  
        float b = ((double*) (integrals->imageData + (cell.y + cell.height) *   
            (integrals->widthStep)))[cell.x + cell.width];  
  
        float c = ((double*) (integrals->imageData + (cell.y) * (integrals-   
            >widthStep)))[cell.x + cell.width];  
  
        float d = ((double*) (integrals->imageData + (cell.y + cell.height) *   
            (integrals->widthStep)))[cell.x];  
  
        ((float*) hog_cell->data.fl) = (a + b) - (c + d);  
  
    }  
  
  
    /*Normalize the matrix*/  
    if (normalization != -1){  
        cvNormalize(hog_cell, hog_cell, 1, 0, normalization);  
    }  
  
}