IntegralImage.cpp
Go to the documentation of this file.
00001 /*
00002  * This file is part of ALVAR, A Library for Virtual and Augmented Reality.
00003  *
00004  * Copyright 2007-2012 VTT Technical Research Centre of Finland
00005  *
00006  * Contact: VTT Augmented Reality Team <alvar.info@vtt.fi>
00007  *          <http://www.vtt.fi/multimedia/alvar.html>
00008  *
00009  * ALVAR is free software; you can redistribute it and/or modify it under the
00010  * terms of the GNU Lesser General Public License as published by the Free
00011  * Software Foundation; either version 2.1 of the License, or (at your option)
00012  * any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful, but WITHOUT
00015  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00016  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00017  * for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public License
00020  * along with ALVAR; if not, see
00021  * <http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html>.
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                 // TODO: Now we assume 'double' - is it ok?
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 /*=0*/) {
00084         int x1 = rect.x;
00085         int x2 = rect.x + rect.width; // Note, not -1
00086         int y1 = rect.y;
00087         int y2 = rect.y + rect.height;
00088         //cout<<x1<<","<<y1<<"-"<<x2<<","<<y2<<endl;
00089         /*
00090         double v = +cvGet2D(sum, y2, x2).val[0]
00091                    -cvGet2D(sum, y2, x1).val[0]
00092                            -cvGet2D(sum, y1, x2).val[0]
00093                            +cvGet2D(sum, y1, x1).val[0];
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                         //cout<<"res: "<<sum->height<<","<<sum->width<<" - ";
00113             //cout<<xi<<","<<yi<<": "<<rect.x<<","<<rect.y<<": "<<xx.get()<<","<<yy.get()<<endl;
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             //cvSet2D(sub, yi, xi, cvScalar(ave));
00123                         // TODO: Now we assume 8-bit gray
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             // As we assume top-left coordinates we have these reverse compared to Donahue1992
00144             double a4 = cvGet2D(gray, j, i+1).val[0];
00145             double a3 = cvGet2D(gray, j, i).val[0];
00146             double a2 = cvGet2D(gray, j+1, i).val[0];
00147             double a1 = cvGet2D(gray, j+1, i+1).val[0];
00148             // Normal vectors;
00149             double nx = (-a1+a2+a3-a4)/4; 
00150             double ny = (-a1-a2+a3+a4)/4;
00151             cvSet2D(normalx, j, i, cvScalar(nx));
00152             cvSet2D(normaly, j, i, cvScalar(ny));
00153                         */
00154             // As we assume top-left coordinates we have these reverse compared to Donahue1992
00155                         // TODO: Now we assume 8-bit gray
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             // Normal vectors;
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 /*=0*/) {
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 } // namespace alvar


ar_track_alvar
Author(s): Scott Niekum
autogenerated on Sat Dec 28 2013 16:46:15