// combine the (xdiv-1)*(ydiv-1) integral images into a single one void DetectionScanner::InitIntegralImages(const int stepsize) { if(cascade->nodes[0]->type!=NodeDetector::LINEAR) return; // No need to prepare integral images const int hd = height/xdiv*2-2; const int wd = width/ydiv*2-2; scores.Create(ct.nrow,ct.ncol); scores.Zero(cascade->nodes[0]->thresh/hd/wd); double* linearweights = cascade->nodes[0]->classifier.buf; for(int i=0; i<xdiv-EXT; i++) { const int xoffset = height/xdiv*i; for(int j=0; j<ydiv-EXT; j++) { const int yoffset = width/ydiv*j; for(int x=2; x<ct.nrow-2-xoffset; x++) { int* ctp = ct.p[x+xoffset]+yoffset; double* tempp = scores.p[x]; for(int y=2; y<ct.ncol-2-yoffset; y++) tempp[y] += linearweights[ctp[y]]; } linearweights += baseflength; } } scores.CalcIntegralImageInPlace(); for(int i=2; i<ct.nrow-2-height; i+=stepsize) { double* p1 = scores.p[i]; double* p2 = scores.p[i+hd]; for(int j=2; j<ct.ncol-2-width; j+=stepsize) p1[j] += (p2[j+wd] - p2[j] - p1[j+wd]); } }
void IntImage<T>::Sobel(IntImage<REAL>& result,const bool useSqrt,const bool normalize) { // compute the Sobel gradient. For now, we just use the very inefficient way. Optimization can be done later // if useSqrt = true, we compute the real Sobel gradient; otherwise, the square of it // if normalize = true, the numbers are normalized to be in 0..255 result.Create(nrow,ncol); for(int i=0; i<nrow; i++) result.p[i][0] = result.p[i][ncol-1] = 0; std::fill(result.p[0],result.p[0]+ncol,0.0); std::fill(result.p[nrow-1],result.p[nrow-1]+ncol,0.0); for(int i=1; i<nrow-1; i++) { T* p1 = p[i-1]; T* p2 = p[i]; T* p3 = p[i+1]; REAL* pr = result.p[i]; for(int j=1; j<ncol-1; j++) { REAL gx = p1[j-1] - p1[j+1] + 2*(p2[j-1] - p2[j+1]) + p3[j-1] - p3[j+1]; REAL gy = p1[j-1] - p3[j-1] + 2*(p1[j] - p3[j]) + p1[j+1] - p3[j+1]; pr[j] = gx*gx+gy*gy; } } if(useSqrt || normalize ) // if we want to normalize the result image, we'd better use the true Sobel gradient for(int i=1; i<nrow-1; i++) for(int j=1; j<ncol-1; j++) result.p[i][j] = sqrt(result.p[i][j]); if(normalize) { REAL minv = 1e20, maxv = -minv; for(int i=1; i<nrow-1; i++) { for(int j=1; j<ncol-1; j++) { if(result.p[i][j]<minv) minv = result.p[i][j]; else if(result.p[i][j]>maxv) maxv = result.p[i][j]; } } for(int i=0; i<nrow; i++) result.p[i][0] = result.p[i][ncol-1] = minv; for(int i=0; i<ncol; i++) result.p[0][i] = result.p[nrow-1][i] = minv; REAL s = 255.0/(maxv-minv); for(int i=0; i<nrow*ncol; i++) result.buf[i] = (result.buf[i]-minv)*s; } }
// compute the Sobel image "ct" from "original" void ComputeCT(IntImage<double>& original,IntImage<int>& ct) { ct.Create(original.nrow,original.ncol); for(int i=2; i<original.nrow-2; i++) { double* p1 = original.p[i-1]; double* p2 = original.p[i]; double* p3 = original.p[i+1]; int* ctp = ct.p[i]; for(int j=2; j<original.ncol-2; j++) { int index = 0; if(p2[j]<=p1[j-1]) index += 0x80; if(p2[j]<=p1[j]) index += 0x40; if(p2[j]<=p1[j+1]) index += 0x20; if(p2[j]<=p2[j-1]) index += 0x10; if(p2[j]<=p2[j+1]) index += 0x08; if(p2[j]<=p3[j-1]) index += 0x04; if(p2[j]<=p3[j]) index += 0x02; if(p2[j]<=p3[j+1]) index ++; ctp[j] = index; } } }