Exemple #1
0
// ######################################################################
void BitObject::computeSecondMoments()
{
  ASSERT(isValid());

  int w = itsObjectMask.getWidth();
  int h = itsObjectMask.getHeight();

  // The bounding box is stored in image coordinates, and so is the centroid. For
  // computing the second moments, however we need the centroid in object coords.
  float cenX = itsCentroidXY.x() - itsBoundingBox.left();
  float cenY = itsCentroidXY.y() - itsBoundingBox.top();

  // compute the second moments
  std::vector<float> diffX(w), diffX2(w), diffY(h), diffY2(h);
  for (int y = 0; y < h; ++y) 
    {
      diffY[y] = y - cenY;
      diffY2[y] = diffY[y] * diffY[y];
    }
  for (int x = 0; x < w; ++x) 
    {
      diffX[x] = x - cenX;
      diffX2[x] = diffX[x] * diffX[x];
    }

  Image<byte>::const_iterator optr = itsObjectMask.begin();
  for (int y = 0; y < h; ++y)
    for(int x = 0; x < w; ++x)
      {
        if (*optr != 0)
          {
            itsUxx += diffX2[x];
            itsUyy += diffY2[y];
            itsUxy += (diffX[x] * diffY[y]);
          }
        ++optr;
      }
  itsUxx /= itsArea; 
  itsUyy /= itsArea;
  itsUxy /= itsArea;

  // compute the parameters d, e and f for the ellipse:
  // d*x^2 + 2*e*x*y + f*y^2 <= 1
  float coeff = 0.F;
  if((itsUxx * itsUyy - itsUxy * itsUxy) > 0)
    coeff = 1 / (4 * (itsUxx * itsUyy - itsUxy * itsUxy));
  float d =  coeff * itsUyy;
  float e = -coeff * itsUxy;
  float f =  coeff * itsUxx;

  // from these guys, compute the parameters d and f for the
  // ellipse when it is rotated so that x is the main axis
  // and figure out the angle of rotation for this.
  float expr = sqrt(4*e*e + squareOf(d - f));
  float d2 = 0.5 * (d + f + expr);
  float f2 = 0.5 * (d + f - expr);

  // the angle is defined in clockwise (image) coordinates:
  //  --  is 0
  //  \   is 45
  //  |   is 90
  //  /   is 135
  if( d != f)  itsOriAngle = 90 * atan(2 * e / (d - f)) / M_PI;
  else	itsOriAngle = 0.F;
  if (itsUyy > itsUxx) itsOriAngle += 90.0F;
  if (itsOriAngle < 0.0F) itsOriAngle += 180.0F;

  // this checks if itsOriAngle is nan
  if (itsOriAngle != itsOriAngle) itsOriAngle = 0.0F;

  // now get the length of the major and the minor axes:
  if(f2) itsMajorAxis = 2 / sqrt(f2);
  if(d2) itsMinorAxis = 2 / sqrt(d2);
  if(itsMinorAxis) itsElongation = itsMajorAxis / itsMinorAxis;
  else itsElongation = 0.F;
  // We're done
  haveSecondMoments = true;
  return;
}
Exemple #2
0
Feature 
HOGFeatureExtractor::operator()(const CByteImage& img_) const
{
	/******** BEGIN TODO ********/
	// Compute the Histogram of Oriented Gradients feature
	// Steps are:
	// 1) Compute gradients in x and y directions. We provide the 
	//    derivative kernel proposed in the paper in _kernelDx and
	//    _kernelDy.
	// 2) Compute gradient magnitude and orientation
	// 3) Add contribution each pixel to HOG cells whose
	//    support overlaps with pixel. Each cell has a support of size
	//    _cellSize and each histogram has _nAngularBins.
	// 4) Normalize HOG for each cell. One simple strategy that is
	//    is also used in the SIFT descriptor is to first threshold
	//    the bin values so that no bin value is larger than some
	//    threshold (we leave it up to you do find this value) and
	//    then re-normalize the histogram so that it has norm 1. A more 
	//    elaborate normalization scheme is proposed in Dalal & Triggs
	//    paper but we leave that as extra credit.
	// 
	// Useful functions:
	// convertRGB2GrayImage, TypeConvert, WarpGlobal, Convolve

	
	int xCells = ceil(1.*img_.Shape().width  / _cellSize);
	int yCells = ceil(1.*img_.Shape().height / _cellSize);

	CFloatImage HOGHist(xCells, yCells, _nAngularBins);
	HOGHist.ClearPixels();

	CByteImage gray(img_.Shape());
	CFloatImage grayF(img_.Shape().width, img_.Shape().height, 1);

	convertRGB2GrayImage(img_, gray);
	TypeConvert(gray, grayF);

	CFloatImage diffX( img_.Shape()), diffY( img_.Shape());

	Convolve(grayF, diffX, _kernelDx);
	Convolve(grayF, diffY, _kernelDy);
	
	CFloatImage grad(grayF.Shape()), grad2(grayF.Shape());
	CFloatImage angl(grayF.Shape()), angl2(grayF.Shape());
	
	for (int y = 0; y <grayF.Shape().height; y++){
		for (int x = 0; x<grayF.Shape().width; x++) {
			grad2.Pixel(x,y,0) = (diffX.Pixel(x,y,0) * diffX.Pixel(x,y,0) +
							     diffY.Pixel(x,y,0) * diffY.Pixel(x,y,0));
			angl2.Pixel(x,y,0) = atan(diffY.Pixel(x,y,0) / abs(diffY.Pixel(x,y,0)));
		}
	}

	// Bilinear Filter
	ConvolveSeparable(grad2, grad, ConvolveKernel_121,ConvolveKernel_121,1);
	ConvolveSeparable(angl2, angl, ConvolveKernel_121,ConvolveKernel_121,1);
	//WriteFile(diffX, "angle.tga");
	//WriteFile(diffY, "angleG.tga");

	for (int y = 0; y <grayF.Shape().height; y++){
		for (int x = 0; x<grayF.Shape().width; x++) {
			// Fit in the bins
			int a = angl.Pixel(x,y,0) / 3.14 * (_nAngularBins) + _nAngularBins/2;		
			// Histogram
			HOGHist.Pixel(floor(1.*x / _cellSize),
						  floor(1.*y / _cellSize),
						  a) += grad.Pixel(x,y,0);
		}
	}
	
	// Normalization 
	float threshold = 0.7;
	for (int y = 0; y < yCells; y++){
		for (int x = 0; x < xCells; x++){
			float total = 0;
			for (int a = 0; a < _nAngularBins; a++) {
				if (HOGHist.Pixel(x,y,a) > threshold)
					HOGHist.Pixel(x,y,a) = threshold;
				// Sum for normalization
				total += HOGHist.Pixel(x,y,a);
			}
			for (int a = 0;a< _nAngularBins; a++) {
				HOGHist.Pixel(x,y,a) /= total;
				
			}
		}
	}
	
	return HOGHist;
	/******** END TODO ********/

}