Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "IntegralImage.h"
00025
00026 namespace alvar {
00027
00028 void IntIndex::update_next_step() {
00029 next_step = step;
00030 estep += step_remainder;
00031 if (estep >= steps) {
00032 estep -= steps;
00033 next_step++;
00034 }
00035 }
00036
00037 IntIndex::IntIndex(int _res, int _steps) {
00038 res = _res;
00039 steps = _steps;
00040 operator=(0);
00041 }
00042 int IntIndex::operator=(int v) {
00043 index = 0;
00044 step = res / steps;
00045 step_remainder = res % steps;
00046 estep = 0;
00047 update_next_step();
00048 while ((index+next_step-1) < v) next();
00049 return index;
00050 }
00051 int IntIndex::next() {
00052 index += next_step;
00053 update_next_step();
00054 return index;
00055 }
00056 int IntIndex::get() const {
00057 return index;
00058 }
00059 int IntIndex::get_next_step() const {
00060 return next_step;
00061 }
00062 int IntIndex::end() const {
00063 return res;
00064 }
00065
00066 IntegralImage::IntegralImage() {
00067 sum = 0;
00068 }
00069 IntegralImage::~IntegralImage() {
00070 if (sum) cvReleaseImage(&sum);
00071 }
00072 void IntegralImage::Update(IplImage *gray) {
00073 if ((sum == 0) ||
00074 (sum->height != gray->width+1) ||
00075 (sum->width != gray->height+1))
00076 {
00077 if (sum) cvReleaseImage(&sum);
00078
00079 sum = cvCreateImage(cvSize(gray->width+1, gray->height+1), IPL_DEPTH_64F, 1);
00080 }
00081 cvIntegral(gray, sum);
00082 }
00083 double IntegralImage::GetSum(CvRect &rect, int *count ) {
00084 int x1 = rect.x;
00085 int x2 = rect.x + rect.width;
00086 int y1 = rect.y;
00087 int y2 = rect.y + rect.height;
00088
00089
00090
00091
00092
00093
00094
00095 double v = +((double *)sum->imageData)[y2*sum->width+x2]
00096 -((double *)sum->imageData)[y2*sum->width+x1]
00097 -((double *)sum->imageData)[y1*sum->width+x2]
00098 +((double *)sum->imageData)[y1*sum->width+x1];
00099
00100 if (count) *count = rect.width*rect.height;
00101 return v;
00102 }
00103 double IntegralImage::GetAve(CvRect &rect) {
00104 int count=1;
00105 return GetSum(rect, &count)/count;
00106 }
00107 void IntegralImage::GetSubimage(const CvRect &rect, IplImage *sub) {
00108 int yi=0;
00109 for (IntIndex yy(rect.height, sub->height); yy.get() != yy.end(); yy.next(),yi++) {
00110 int xi=0;
00111 for (IntIndex xx(rect.width, sub->width); xx.get() != xx.end(); xx.next(),xi++) {
00112
00113
00114 CvRect r = {
00115 rect.x+xx.get(),
00116 rect.y+yy.get(),
00117 xx.get_next_step(),
00118 yy.get_next_step()
00119 };
00120 double ave = GetAve(r);
00121
00122
00123
00124 sub->imageData[yi*sub->widthStep+xi] = (char)ave;
00125 }
00126 }
00127 }
00128 void IntegralGradient::CalculatePointNormals(IplImage *gray) {
00129 int width = gray->width-1;
00130 int height = gray->height-1;
00131 if ((normalx == 0) ||
00132 (normalx->width != width) ||
00133 (normalx->height != height))
00134 {
00135 if (normalx) cvReleaseImage(&normalx);
00136 if (normaly) cvReleaseImage(&normaly);
00137 normalx = cvCreateImage(cvSize(width, height), IPL_DEPTH_64F, 1);
00138 normaly = cvCreateImage(cvSize(width, height), IPL_DEPTH_64F, 1);
00139 }
00140 for (int j=0; j<height; j++) {
00141 for (int i=0; i<width; i++) {
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 double a4 = (unsigned char)gray->imageData[(j)*gray->widthStep+(i+1)];
00157 double a3 = (unsigned char)gray->imageData[(j)*gray->widthStep+(i)];
00158 double a2 = (unsigned char)gray->imageData[(j+1)*gray->widthStep+(i)];
00159 double a1 = (unsigned char)gray->imageData[(j+1)*gray->widthStep+(i+1)];
00160
00161 double nx = (-a1+a2+a3-a4)/4;
00162 double ny = (-a1-a2+a3+a4)/4;
00163 ((double *)normalx->imageData)[j*normalx->width+i] = nx;
00164 ((double *)normaly->imageData)[j*normaly->width+i] = ny;
00165 }
00166 }
00167 }
00168 IntegralGradient::IntegralGradient() {
00169 normalx = 0;
00170 normaly = 0;
00171 }
00172 IntegralGradient::~IntegralGradient() {
00173 if (normalx) cvReleaseImage(&normalx);
00174 if (normaly) cvReleaseImage(&normaly);
00175 }
00176 void IntegralGradient::Update(IplImage *gray) {
00177 CalculatePointNormals(gray);
00178 integx.Update(normalx);
00179 integy.Update(normaly);
00180 }
00181 void IntegralGradient::GetGradient(CvRect &rect, double *dirx, double *diry, int *count ) {
00182 CvRect r = {rect.x, rect.y, rect.width-1, rect.height-1};
00183 if (count) *dirx = integx.GetSum(r, count);
00184 else *dirx = integx.GetSum(r);
00185 *diry = integy.GetSum(r);
00186 }
00187 void IntegralGradient::GetAveGradient(CvRect &rect, double *dirx, double *diry) {
00188 int count=1;
00189 GetGradient(rect, dirx, diry, &count);
00190 *dirx /= count;
00191 *diry /= count;
00192 }
00193
00194 }