oriented_gradient.cpp
Go to the documentation of this file.
00001 // @brief calc oriented gradent
00002 // @author Hiroaki Yaguchi, JSK
00003 #include "jsk_perception/oriented_gradient.hpp"
00004 
00005 namespace jsk_perception {
00006 
00007 // @brief calc 8 neighbor oriented gradient image
00008 // @param src source image
00009 // @param dst destination image (HSV, H : orientation, V : intensity)
00010 void calcOrientedGradient(cv::Mat& src, cv::Mat& dst) {
00011   int width, height;
00012   cv::Mat gimg;
00013 
00014   width = src.cols;
00015   height = src.rows;
00016 
00017   cv::cvtColor(src, gimg, CV_BGR2GRAY);
00018 
00019   dst.create(height, width, CV_8UC3);
00020   for (int y = 0; y < height; y++) {
00021     for (int x = 0; x < width; x++) {
00022       cv::Vec3b& px=dst.at<cv::Vec3b>(y, x);
00023       for (int k = 0; k < 3; k++) {
00024         px[k] = 0;
00025       }
00026     }
00027   }
00028 
00029   float r2 = sqrt(2.0);
00030 
00031   for (int y = 1; y < height - 1; y++) {
00032     for (int x = 1; x < width - 1; x++) {
00033       int m,th;
00034       float dx,dy;
00035       float dxx,dyy,dxy,dyx;
00036       double dth;
00037 
00038       dxx = (float)gimg.at<unsigned char>(y, x + 1)
00039         - (float)gimg.at<unsigned char>(y, x - 1);
00040       dyy = (float)gimg.at<unsigned char>(y + 1, x)
00041         - (float)gimg.at<unsigned char>(y - 1, x);
00042       dxy = (float)gimg.at<unsigned char>(y + 1, x + 1)
00043         - (float)gimg.at<unsigned char>(y - 1, x - 1);
00044       dyx = (float)gimg.at<unsigned char>(y + 1, x - 1)
00045         - (float)gimg.at<unsigned char>(y - 1, x + 1);
00046 
00047       dx = 0.5 * (dxx + 0.5 * r2 * (dxy - dyx));
00048       dy = 0.5 * (dyy + 0.5 * r2 * (dxy + dyx));
00049       // dx = dxx; dy = dyy;
00050 
00051       m = (int)(sqrt(0.5 * (dx * dx + dy * dy)));
00052 
00053       dth = atan2(dy, dx) * 180.0 / M_PI;
00054       if (dth < 0.0) dth += 180.0;
00055       if (dth >= 180.0) dth -= 180.0;
00056       th = (int)dth;
00057 
00058       dst.at<cv::Vec3b>(y, x) = cv::Vec3b(th, 255, m);
00059 
00060     }
00061   }
00062 }
00063 
00064 // @brief calc key points from oriented gradient image
00065 // @param src source image
00066 // @param dst destination image (HSV, H : orientation, V : intensity)
00067 // @param result key points
00068 // @param thres (optional) threshold of intensity
00069 // @param bs (optional) block size
00070 void calcOGKeyPoints(cv::Mat& src,
00071                      cv::Mat& dst,
00072                      std::vector<cv::Point>& result,
00073                      int thres,
00074                      int bs) {
00075   calcOrientedGradient(src, dst);
00076   int width, height;
00077   width = src.cols;
00078   height = src.rows;
00079 
00080   result.clear();
00081 
00082   for (int y = bs; y < height - bs; y++) {
00083     for (int x = bs; x < width - bs; x++) {
00084       cv::Vec3b& px0 = dst.at<cv::Vec3b>(y, x);
00085       if (px0[2] > thres) {
00086         bool iskey = true;
00087         for (int dx = -bs; dx <= bs; dx++) {
00088           for (int dy = -bs; dy <= bs; dy++) {
00089             if (dx == 0 && dy == 0) break;
00090             cv::Vec3b& px1 = dst.at<cv::Vec3b>(y + dy, x + dx);
00091             if (px0[2] < px1[2]) iskey = false;
00092           }
00093         }
00094         if (iskey) result.push_back(cv::Point(x, y));
00095       }
00096 
00097     }
00098   }
00099 
00100 }
00101 
00102 // @brief calc 8 neighbor scaled oriented gradient image
00103 // @param src source image
00104 // @param dst destination image (HSV, H : orientation, V : intensity)
00105 // @param scale scale
00106 void calcScaledOrientedGradient(cv::Mat& src, cv::Mat& dst, int scale) {
00107   cv::Mat gimg;
00108   cv::Mat intimg, sqintimg, tintimg;
00109 
00110   int width = src.cols;
00111   int height = src.rows;
00112 
00113   cv::cvtColor(src, gimg, CV_BGR2GRAY);
00114 
00115   dst.create(height, width, CV_8UC3);
00116   unsigned char *gradbuf = dst.ptr();
00117 
00118   intimg.create(height + 1, width + 1, CV_32S);
00119   sqintimg.create(height + 1, width + 1, CV_32S);
00120   tintimg.create(height + 1, width + 1, CV_32S);
00121 
00122   cv::integral(gimg, intimg, sqintimg, tintimg);
00123 
00124   float r2 = sqrt(2.0);
00125   int xidx, idx;
00126   int hscale = scale / 2;
00127   int bsize = hscale * 2 + 1;
00128   int barea0 = scale * scale;
00129   int barea1 = scale * bsize;
00130   int margin = scale;
00131   for (int y = margin; y < height - margin; y++) {
00132     xidx = y * width;
00133     for (int x = margin; x < width - margin; x++) {
00134       int m, th;
00135       float dx, dy;
00136       float dxx, dyy, dxy, dyx;
00137       double dth;
00138 
00139       dxx = ((float)(intimg.at<int>(y + hscale + 1, x + scale + 1)
00140                      + intimg.at<int>(y - hscale, x + 1)
00141                      - intimg.at<int>(y - hscale, x + scale + 1)
00142                      - intimg.at<int>(y + hscale + 1, x + 1))
00143              - (float)(intimg.at<int>(y + hscale + 1, x)
00144                        +intimg.at<int>(y - hscale, x - scale)
00145                        -intimg.at<int>(y - hscale, x)
00146                        -intimg.at<int>(y + hscale + 1, x - scale))) / barea1;
00147       dyy = ((float)(intimg.at<int>(y + scale + 1, x + hscale + 1)
00148                      + intimg.at<int>(y + 1, x - hscale)
00149                      - intimg.at<int>(y + scale + 1, x - hscale)
00150                      - intimg.at<int>(y + 1, x + hscale + 1))
00151              - (float)(intimg.at<int>(y - scale, x - hscale)
00152                        +intimg.at<int>(y, x + hscale + 1)
00153                        -intimg.at<int>(y - scale, x + hscale + 1)
00154                        -intimg.at<int>(y, x - hscale))) / barea1;
00155 
00156       dxy = ((float)(intimg.at<int>(y + scale + 1, x + scale + 1)
00157                      + intimg.at<int>(y + 1, x + 1)
00158                      - intimg.at<int>(y + 1, x + scale + 1)
00159                      - intimg.at<int>(y + scale + 1, x + 1))
00160              - (float)(intimg.at<int>(y, x)
00161                        + intimg.at<int>(y - scale, x - scale)
00162                        - intimg.at<int>(y, x - scale)
00163                        - intimg.at<int>(y - scale, x))) / barea0;
00164       dyx = ((float)(intimg.at<int>(y + scale + 1, x)
00165                      + intimg.at<int>(y + 1, x - scale)
00166                      - intimg.at<int>(y + 1, x)
00167                      - intimg.at<int>(y + scale + 1, x - scale))
00168              - (float)(intimg.at<int>(y, x + scale + 1)
00169                        + intimg.at<int>(y - scale, x + 1)
00170                        - intimg.at<int>(y - scale, x + scale + 1)
00171                        - intimg.at<int>(y, x + 1))) / barea0;
00172 
00173       dx = 0.5 * (dxx + 0.5 * r2 * (dxy - dyx));
00174       dy = 0.5 * (dyy + 0.5 * r2 * (dxy + dyx));
00175 
00176       m = (int)(sqrt(0.5 * (dx * dx + dy * dy)));
00177 
00178       dth = atan2(dy, dx) * 180.0 / M_PI;
00179       if (dth < 0.0) dth += 180.0;
00180       if (dth >= 180.0) dth -= 180.0;
00181       th = (int)dth;
00182 
00183       gradbuf[(xidx + x) * 3] = th;
00184       gradbuf[(xidx + x) * 3 + 1] = 255;
00185       gradbuf[(xidx + x) * 3 + 2] = m;
00186     }
00187   }
00188 }
00189 
00190 // @brief calc key points from scaled oriented gradient image
00191 // @param src source image
00192 // @param dst destination image (HSV, H : orientation, V : intensity)
00193 void calcSOGKeyPoints(cv::Mat& src, cv::Mat& dst) {
00194   cv::Mat gimg;
00195   cv::Mat intimg, sqintimg, tintimg;
00196 
00197   int width = src.cols;
00198   int height = src.rows;
00199 
00200   std::vector<std::vector<float> > gradimglist;
00201   std::vector<int> scalelist;
00202 
00203   cv::cvtColor(src, gimg, CV_BGR2GRAY);
00204 
00205   dst.create(height, width, CV_8UC3);
00206   unsigned char *gradbuf = dst.ptr();
00207 
00208   intimg.create(height + 1, width + 1, CV_32S);
00209   sqintimg.create(height + 1, width + 1, CV_32S);
00210   tintimg.create(height + 1, width + 1, CV_32S);
00211 
00212   cv::integral(gimg, intimg, sqintimg, tintimg);
00213 
00214   // scale=1,1+1*2,1+2*2,...,1+s*2
00215   int maxscale = 10;
00216   scalelist.resize(width * height);
00217 
00218   // gradimglist = g(0) gx(0), gy(0), ...
00219   gradimglist.resize((maxscale + 1) * 3);
00220 
00221   for(int i = 0; i < gradimglist.size(); i++)
00222     gradimglist[i].resize(width * height);
00223 
00224   // s=1
00225   float r2 = sqrt(2.0);
00226   int xidx, idx;
00227   for (int y = 1; y < height - 1; y++) {
00228     xidx = y * width;
00229     for (int x = 1; x < width - 1; x++) {
00230       float dx, dy;
00231       float dxx, dyy, dxy, dyx;
00232 
00233       dxx = (float)gimg.at<unsigned char>(y, x + 1)
00234         - (float)gimg.at<unsigned char>(y, x - 1);
00235       dyy = (float)gimg.at<unsigned char>(y + 1, x)
00236         - (float)gimg.at<unsigned char>(y - 1, x);
00237       dxy = (float)gimg.at<unsigned char>(y + 1, x + 1)
00238         - (float)gimg.at<unsigned char>(y - 1, x - 1);
00239       dyx = (float)gimg.at<unsigned char>(y + 1, x - 1)
00240         - (float)gimg.at<unsigned char>(y - 1, x + 1);
00241 
00242       dx = 0.5 * (dxx + 0.5 * r2 * (dxy - dyx));
00243       dy = 0.5 * (dyy + 0.5 * r2 * (dxy + dyx));
00244 
00245       idx = xidx + x;
00246       gradimglist[0][idx] = dx * dx + dy * dy;
00247       gradimglist[1][idx] = dx;
00248       gradimglist[2][idx] = dy;
00249     }
00250   }
00251 
00252   // s >= 2
00253   for (int scale = 2; scale <= maxscale; scale++) {
00254 
00255     int hscale = scale / 2;
00256     int bsize = hscale * 2 + 1;
00257     int barea0 = scale * scale;
00258     int barea1 = scale * bsize;
00259     int margin = scale;
00260 
00261     int sidx = (scale - 1) * 3;
00262     for (int y = margin; y < height - margin; y++) {
00263       xidx = y * width;
00264       for (int x = margin; x < width - margin; x++) {
00265         float dx, dy;
00266         float dxx, dyy, dxy, dyx;
00267 
00268         dxx = ((float)(intimg.at<int>(y + hscale + 1, x + scale + 1)
00269                        + intimg.at<int>(y - hscale, x + 1)
00270                        - intimg.at<int>(y - hscale, x + scale + 1)
00271                        - intimg.at<int>(y + hscale + 1, x + 1))
00272                - (float)(intimg.at<int>(y + hscale + 1, x)
00273                          + intimg.at<int>(y - hscale, x - scale)
00274                          - intimg.at<int>(y - hscale, x)
00275                          - intimg.at<int>(y + hscale + 1, x - scale)))
00276             / barea1;
00277         dyy = ((float)(intimg.at<int>(y + scale + 1, x + hscale + 1)
00278                        + intimg.at<int>(y + 1, x - hscale)
00279                        - intimg.at<int>(y + scale + 1, x - hscale)
00280                        - intimg.at<int>(y + 1, x + hscale + 1))
00281                -(float)(intimg.at<int>(y - scale, x - hscale)
00282                         +intimg.at<int>(y, x + hscale + 1)
00283                         -intimg.at<int>(y - scale, x + hscale + 1)
00284                         -intimg.at<int>(y, x - hscale))) / barea1;
00285 
00286 
00287         dxy = ((float)(intimg.at<int>(y + scale + 1, x + scale + 1)
00288                        + intimg.at<int>(y + 1, x + 1)
00289                        - intimg.at<int>(y + 1, x + scale + 1)
00290                        - intimg.at<int>(y + scale + 1, x + 1))
00291                - (float)(intimg.at<int>(y, x)
00292                          + intimg.at<int>(y - scale, x - scale)
00293                          - intimg.at<int>(y, x - scale)
00294                          - intimg.at<int>(y - scale, x))) / barea0;
00295         dyx = ((float)(intimg.at<int>(y + scale + 1, x)
00296                        + intimg.at<int>(y + 1, x - scale)
00297                        - intimg.at<int>(y + 1, x)
00298                        - intimg.at<int>(y + scale + 1, x - scale))
00299                - (float)(intimg.at<int>(y, x + scale + 1)
00300                          + intimg.at<int>(y - scale, x + 1)
00301                          - intimg.at<int>(y - scale, x + scale + 1)
00302                          - intimg.at<int>(y, x + 1))) / barea0;
00303 
00304         dx = 0.5 * (dxx + 0.5 * r2 * (dxy - dyx));
00305         dy = 0.5 * (dyy + 0.5 * r2 * (dxy + dyx));
00306 
00307         idx = xidx + x;
00308         gradimglist[sidx][idx] = dx * dx + dy * dy;
00309         gradimglist[sidx + 1][idx] = dx;
00310         gradimglist[sidx + 2][idx] = dy;
00311       }
00312     }
00313   }
00314 
00315   // scale estimation
00316   int ofs = 1 + maxscale;
00317   for (int y = ofs; y < height - ofs; y++) {
00318     xidx = y * width;
00319     for (int x = ofs; x < width - ofs; x++) {
00320       idx = xidx + x;
00321       float m, mmax, th;
00322       int sscale = 0;
00323       int mscale = sscale;
00324       float dx, dy;
00325       mmax = gradimglist[sscale][idx];
00326       for (int scale = sscale + 1; scale <= maxscale; scale++) {
00327         m = gradimglist[scale * 3][idx];
00328         if (mmax < m) {
00329           mmax = m;
00330           mscale = scale;
00331         } else {
00332           break;
00333         }
00334       }
00335       m = sqrt(mmax);
00336       dx = gradimglist[mscale * 3 + 1][idx];
00337       dy = gradimglist[mscale * 3 + 2][idx];
00338       th = atan2(dy, dx) * 180.0 / M_PI;
00339       if (th < 0.0) th += 180.0;
00340       if (th >= 180.0) th -= 180.0;
00341       scalelist[idx] = mscale;
00342 
00343       gradbuf[idx * 3] = (unsigned char)th;
00344       gradbuf[idx * 3 + 1] = 255;
00345       gradbuf[idx * 3 + 2] = (unsigned char)m;
00346     }
00347   }
00348 
00349   // keypoint localization
00350   for (int y = ofs; y < height - ofs; y++) {
00351     xidx = y * width;
00352     for (int x = ofs; x < width - ofs; x++) {
00353       idx = xidx + x;
00354       int scale = scalelist[idx];
00355       float m = gradimglist[scale][idx];
00356       bool iskey = false;
00357       if (sqrt(m) > 32) {
00358         iskey = true;
00359         for (int sc = scale > 0 ? scale - 1 : 0;
00360              sc < (scale < maxscale ? scale + 1 : maxscale);
00361              sc++) {
00362           for (int xx = -1; xx <= 1; xx++) {
00363             if (m < gradimglist[sc][idx + xx]
00364                 || m < gradimglist[sc][idx + xx + width]
00365                 || m < gradimglist[sc][idx + xx - width]) {
00366               iskey = false;
00367               break;
00368             }
00369           }
00370         }
00371       }
00372 
00373       if (iskey) {
00374         cv::circle(src,
00375                    cv::Point(x, y),
00376                    scale + 1,
00377                    cv::Scalar(0, 0, 255),
00378                    1,
00379                    4);
00380       } else {
00381         // gradbuf[idx*3]=0;
00382         // gradbuf[idx*3+1]=0;
00383         // gradbuf[idx*3+2]=0;
00384       }
00385     }
00386   }
00387 }
00388 
00389 
00390 }  // namespace


jsk_perception
Author(s): Manabu Saito
autogenerated on Mon Oct 6 2014 01:16:59