Exemple #1
0
Feature 
TinyImageFeatureExtractor::operator()(const CByteImage& img_) const
{
	CFloatImage tinyImg(_targetW, _targetH, 1);

	/******** BEGIN TODO ********/
	// Compute tiny image feature, output should be _targetW by _targetH a grayscale image
	// Steps are:
	// 1) Convert image to grayscale (see convertRGB2GrayImage in Utils.h)
	// 2) Resize image to be _targetW by _targetH
	// 
	// Useful functions:
	// convertRGB2GrayImage, TypeConvert, WarpGlobal

	
	CByteImage gray;
	CFloatImage grayF;
	convertRGB2GrayImage(img_, gray);
	TypeConvert(gray, grayF);
	CTransform3x3 scale = CTransform3x3::Scale(1.* img_.Shape().width / _targetW,
											   1.* img_.Shape().height/ _targetH);
	
	WarpGlobal(grayF, tinyImg, scale, eWarpInterpLinear);

	 

	/******** END TODO ********/

	return tinyImg;
}
void rotation()
{	
		CFloatImage matrixImage = GetImageFromMatrix((float *)featureMatrix, 10, 10);
		CTransform3x3 translationNegative;
		CTransform3x3 translationPositive;
		CTransform3x3 rotation;
		CFloatImage postHomography;

		Feature f;
		f.x = 6;
		f.y = 5;
		f.angleRadians = PI;

		translationNegative = translationNegative.Translation(f.x,f.y);
		translationPositive = translationPositive.Translation(-f.x,-f.y);

		rotation = rotation.Rotation(-f.angleRadians * 180/ PI);


		WarpGlobal(matrixImage, postHomography, translationNegative*rotation*translationPositive, eWarpInterpLinear, eWarpInterpNearest);
		for (int i = 0; i < postHomography.Shape().height; i++)
		{
			for (int j = 0; j < postHomography.Shape().width; j++)
			{
				printf("%.0f\t", postHomography.Pixel(j, i, 0));
			}
			printf("\n");
		}
}
Exemple #3
0
void WarpInstantiate(void)
{
    CByteImage i1;
    CFloatImage uv1;
    WarpLocal(i1, i1, uv1, false, eWarpInterpLinear, 1.0f);
    CTransform3x3 M;
    WarpGlobal(i1, i1, M, eWarpInterpLinear, 1.0f);
}
/******************* TO DO 5 *********************
 * BlendImages:
 *	INPUT:
 *		ipv: list of input images and their relative positions in the mosaic
 *		blendWidth: width of the blending function
 *	OUTPUT:
 *		create & return final mosaic by blending all images
 *		and correcting for any vertical drift
 */
CByteImage BlendImages(CImagePositionV& ipv, float blendWidth)
{
    // Assume all the images are of the same shape (for now)
    CByteImage& img0 = ipv[0].img;
    CShape sh        = img0.Shape();
    int width        = sh.width;
    int height       = sh.height;
    int nBands       = sh.nBands;
    int dim[2]       = {width, height};

    // Compute the bounding box for the mosaic
    int n = ipv.size();
    float min_x = 0, min_y = 0;
    float max_x = 0, max_y = 0;
    int i;
	float dy = 0;
    for (i = 0; i < n; i++)
    {
		
		CTransform3x3 &pos = ipv[i].position;

        CVector3 corners[4];//表示图片的4个角的坐标,分别为左下,右下,左上,右上

        corners[0][0] = 0.0;
        corners[0][1] = 0.0;
        corners[0][2] = 1.0;

        corners[1][0] = width - 1;
        corners[1][1] = 0.0;
        corners[1][2] = 1.0;

        corners[2][0] = 0.0;
        corners[2][1] = height - 1;
        corners[2][2] = 1.0;

        corners[3][0] = width - 1;
        corners[3][1] = height - 1;
        corners[3][2] = 1.0;

        corners[0] = pos * corners[0];
        corners[1] = pos * corners[1];
        corners[2] = pos * corners[2];
        corners[3] = pos * corners[3];

        corners[0][0] /= corners[0][2];
        corners[0][1] /= corners[0][2];

        corners[1][0] /= corners[0][2];
        corners[1][1] /= corners[0][2];

        corners[2][0] /= corners[0][2];
        corners[2][1] /= corners[0][2];

        corners[3][0] /= corners[0][2];
        corners[3][1] /= corners[0][2];
        
		// *** BEGIN TODO #1 ***
		// add some code here to update min_x, ..., max_y
		//Use c0 and c3 to get the range of x and y.
		int iminx, iminy, imaxx, imaxy;
        ImageBoundingBox(img0, pos, iminx, iminy, imaxx, imaxy);

        if (i == 0) 
		{ 
			dy += imaxy; 
		}
        if (i == n - 1) 
		{ 
			dy -= imaxy; 
		}
		/*if (min_x > corners[0][0])
		{
			min_x = corners[0][0];
		}
		if (max_x < corners[3][0])
		{
			max_x = corners[3][0];
		}
		if (min_y > corners[0][1])
		{
			min_y = corners[0][1];
		}
		if (max_y < corners[3][1])
		{
			max_y = corners[3][1];
		}
		*/
		min_x = min(min_x, float(iminx));
        min_y = min(min_y, float(iminy));
        max_x = max(max_x, float(imaxx));
        max_y = max(max_y, float(imaxy));

		// *** END TODO #1 ***
    }

    // Create a floating point accumulation image
    CShape mShape((int)(ceil(max_x) - floor(min_x)),
                  (int)(ceil(max_y) - floor(min_y)), nBands);
    CFloatImage accumulator(mShape);
    accumulator.ClearPixels();

	double x_init, x_final;
    double y_init, y_final;

	// Add in all of the images
    for (i = 0; i < n; i++) {
        
        CTransform3x3 &M = ipv[i].position;

        CTransform3x3 M_t = CTransform3x3::Translation(-min_x, -min_y) * M;

        CByteImage& img = ipv[i].img;

        // Perform the accumulation
		AccumulateBlend(img, accumulator, M_t, blendWidth);

        if (i == 0) {
            CVector3 p;
            p[0] = 0.5 * width;
            p[1] = 0.0;
            p[2] = 1.0;

            p = M_t * p;
            x_init = p[0];
            y_init = p[1];
        } else if (i == n - 1) {
            CVector3 p;
            p[0] = 0.5 * width;
            p[1] = 0.0;
            p[2] = 1.0;

            p = M_t * p;
            x_final = p[0];
            y_final = p[1];
        }
    }



    // Normalize the results
    CByteImage compImage(mShape);
    NormalizeBlend(accumulator, compImage);
    bool debug_comp = false;
    if (debug_comp)
        WriteFile(compImage, "tmp_comp.tga");

    // Allocate the final image shape
    CShape cShape(mShape.width - width, height, nBands);
    CByteImage croppedImage(cShape);

    // Compute the affine deformation
    CTransform3x3 A = CTransform3x3();
    
	// *** BEGIN TODO #2 ***
    // fill in the right entries in A to trim the left edge and
    // to take out the vertical drift
	A[0][2] = width /2;
	A[1][0] = dy / (mShape.width - width);


	// *** END TODO #2 ***

    // Warp and crop the composite
    WarpGlobal(compImage, croppedImage, A, eWarpInterpLinear);
//	WarpGlobal(compImage, croppedImage, A, eWarpInterpNearest); //similar as linear
//	WarpGlobal(compImage, croppedImage, A, eWarpInterpCubic); //all pixels are black

    return croppedImage;
}
// Compute MOPs descriptors.
void ComputeMOPSDescriptors(CFloatImage &image, FeatureSet &features)
{
	CFloatImage grayImage=ConvertToGray(image);
	CFloatImage blurredImage;
	
	Convolve(grayImage, blurredImage, ConvolveKernel_7x7);

	CFloatImage postHomography = CFloatImage();
	CFloatImage gaussianImage = GetImageFromMatrix((float *)gaussian5x5Float, 5, 5);


	//first make the image invariant to changes in illumination by subtracting off the mean
	int grayHeight = grayImage.Shape().height;
	int grayWidth = grayImage.Shape().width;

	// now make this rotation invariant
    vector<Feature>::iterator featureIterator = features.begin();
    while (featureIterator != features.end()) {
		Feature &f = *featureIterator;

		CTransform3x3 scaleTransform = CTransform3x3();
		CTransform3x3 translationNegative;
		CTransform3x3 translationPositive;
		CTransform3x3 rotation;

		double scaleFactor = 41/8;
		scaleTransform[0][0] = scaleFactor;
		scaleTransform[1][1] = scaleFactor;

		translationNegative = translationNegative.Translation(f.x,f.y);
		translationPositive = translationPositive.Translation(-4, -4);
		rotation = rotation.Rotation(f.angleRadians * 180/ PI);
		
		CTransform3x3 finalTransformation = translationNegative * rotation * scaleTransform * translationPositive;
		//CFloatImage sample61x61Window = 
		//CFloatImage pixelWindow = GetXWindowAroundPixel(grayImage, f.x, f.y, 61);

		WarpGlobal(blurredImage, postHomography, finalTransformation, eWarpInterpLinear, 1.0f);

		//now we get the 41x41 box around the feature
		for(int row=0; row< 8; row++)
		{
			for(int col=0;col< 8;col++)
			{
				f.data.push_back(postHomography.Pixel(col, row, 0));
			}
		}
		/*
		// now we do the subsampling first round to reduce to a 20x20
		int imgSize = 41;
		subsample(&f, imgSize, gaussianImage);

		//second round of subsampling to get it to a 10x10
		imgSize = 20;
		subsample(&f, imgSize, gaussianImage);	

		imgSize = 10;
		CFloatImage img = featureToImage(f, imgSize, imgSize);
		CFloatImage blurredImg(img.Shape());
		Convolve(img, blurredImg, gaussianImage);
		featuresFromImage(&f,blurredImg,imgSize,imgSize);
		
		int count = 0;
		for(int y=0; y<imgSize; y++)
		{
			for(int x=0; x<imgSize; x++)
			{
				if(x == 3 || x == 7 || y == 3 || y == 7)
				{
					f.data.erase(f.data.begin() + count);
				}
				else
				{
					count++;
				}
			}
		}
		*/
		normalizeIntensities(&f, 8, 8);
		featureIterator++;

	}
}
Exemple #6
0
HOGFeatureExtractor::HOGFeatureExtractor(int nAngularBins, bool unsignedGradients, int cellSize):
_nAngularBins(nAngularBins),
_unsignedGradients(unsignedGradients),
_cellSize(cellSize)
{
    _kernelDx.ReAllocate(CShape(3, 1, 1), derivKvals, false, 1);
    _kernelDx.origin[0] = 1;

    _kernelDy.ReAllocate(CShape(1, 3, 1), derivKvals, false, 1);
    _kernelDy.origin[0] = 1;

    // For visualization
    // A set of patches representing the bin orientations. When drawing a hog cell 
    // we multiply each patch by the hog bin value and add all contributions up to 
    // form the visual representation of one cell. Full HOG is achieved by stacking 
    // the viz for individual cells horizontally and vertically.
    _oriMarkers.resize(_nAngularBins);
    const int ms = 11;
    CShape markerShape(ms, ms, 1);

    // First patch is a horizontal line
    _oriMarkers[0].ReAllocate(markerShape, true);
    _oriMarkers[0].ClearPixels();
    for(int i = 1; i < ms - 1; i++) _oriMarkers[0].Pixel(/*floor(*/ ms/2 /*)*/, i, 0) = 1;

#if 0 // debug
	std::cout << "DEBUG:" << __FILE__ << ":" << __LINE__ << std::endl;
	for(int i = 0; i < ms; i++) {
		for(int j = 0; j < ms; j++) {
			std::cout << _oriMarkers[0].Pixel(j, i, 0) << " ";
		}
		std::cout << std::endl;
	}
	std::cout << std::endl;

	char debugFName[2000];
	sprintf(debugFName, "/tmp/debug%03d.tga", 0);
	PRINT_EXPR(debugFName);
	WriteFile(_oriMarkers[0], debugFName);
#endif

	// The other patches are obtained by rotating the first one
	CTransform3x3 T = CTransform3x3::Translation((ms - 1) / 2.0, (ms - 1) / 2.0);
    for(int angBin = 1; angBin < _nAngularBins; angBin++) {
    	double theta;
    	if(unsignedGradients) theta = 180.0 * (double(angBin) / _nAngularBins);
    	else theta = 360.0 * (double(angBin) / _nAngularBins);
   		CTransform3x3 R  = T * CTransform3x3::Rotation(theta) * T.Inverse();

   		_oriMarkers[angBin].ReAllocate(markerShape, true);
   		_oriMarkers[angBin].ClearPixels();

		WarpGlobal(_oriMarkers[0], _oriMarkers[angBin], R, eWarpInterpLinear);

#if 0 // debug
		char debugFName[2000];
		sprintf(debugFName, "/tmp/debug%03d.tga", angBin);
		PRINT_EXPR(debugFName);
		WriteFile(_oriMarkers[angBin], debugFName);
#endif
    }
}
Exemple #7
0
/******************* TO DO 5 *********************
* BlendImages:
*	INPUT:
*		ipv: list of input images and their relative positions in the mosaic
*		blendWidth: width of the blending function
*	OUTPUT:
*		create & return final mosaic by blending all images
*		and correcting for any vertical drift
*/
CByteImage BlendImages(CImagePositionV& ipv, float blendWidth)
{
    // Assume all the images are of the same shape (for now)
    CByteImage& img0 = ipv[0].img;
    CShape sh        = img0.Shape();
    int width        = sh.width;
    int height       = sh.height;
    int nBands       = sh.nBands;
    // int dim[2]       = {width, height};

    int n = ipv.size();
    if (n == 0) return CByteImage(0,0,1);

    bool is360 = false;

    // Hack to detect if this is a 360 panorama
    if (ipv[0].imgName == ipv[n-1].imgName)
        is360 = true;

    // Compute the bounding box for the mosaic
    float min_x = FLT_MAX, min_y = FLT_MAX;
    float max_x = 0, max_y = 0;
    int i;
    for (i = 0; i < n; i++)
    {
        CTransform3x3 &T = ipv[i].position;

        // BEGIN TODO
        // add some code here to update min_x, ..., max_y
printf("TODO: %s:%d\n", __FILE__, __LINE__); 

        // END TODO
    }

    // Create a floating point accumulation image
    CShape mShape((int)(ceil(max_x) - floor(min_x)),
        (int)(ceil(max_y) - floor(min_y)), nBands + 1);
    CFloatImage accumulator(mShape);
    accumulator.ClearPixels();

    double x_init, x_final;
    double y_init, y_final;

    // Add in all of the images
    for (i = 0; i < n; i++) {
        // Compute the sub-image involved
        CTransform3x3 &M = ipv[i].position;
        CTransform3x3 M_t = CTransform3x3::Translation(-min_x, -min_y) * M;
        CByteImage& img = ipv[i].img;

        // Perform the accumulation
        AccumulateBlend(img, accumulator, M_t, blendWidth);

        if (i == 0) {
            CVector3 p;
            p[0] = 0.5 * width;
            p[1] = 0.0;
            p[2] = 1.0;

            p = M_t * p;
            x_init = p[0];
            y_init = p[1];
        } else if (i == n - 1) {
            CVector3 p;
            p[0] = 0.5 * width;
            p[1] = 0.0;
            p[2] = 1.0;

            p = M_t * p;
            x_final = p[0];
            y_final = p[1];
        }
    }

    // Normalize the results
    mShape = CShape((int)(ceil(max_x) - floor(min_x)),
        (int)(ceil(max_y) - floor(min_y)), nBands);

    CByteImage compImage(mShape);
    NormalizeBlend(accumulator, compImage);
    bool debug_comp = false;
    if (debug_comp)
        WriteFile(compImage, "tmp_comp.tga");

    // Allocate the final image shape
    int outputWidth = 0;
    if (is360) {
        outputWidth = mShape.width - width;
    } else {
        outputWidth = mShape.width;
    }

    CShape cShape(outputWidth, mShape.height, nBands);

    CByteImage croppedImage(cShape);

    // Compute the affine transformation
    CTransform3x3 A = CTransform3x3(); // identify transform to initialize

    // BEGIN TODO
    // fill in appropriate entries in A to trim the left edge and
    // to take out the vertical drift if this is a 360 panorama
    // (i.e. is360 is true)
printf("TODO: %s:%d\n", __FILE__, __LINE__); 

    // END TODO

    // Warp and crop the composite
    WarpGlobal(compImage, croppedImage, A, eWarpInterpLinear);

    return croppedImage;
}
Exemple #8
0
// Compute MOPs descriptors.
void ComputeMOPSDescriptors(CFloatImage &image, FeatureSet &features)
{
	int w = image.Shape().width;  // image width
	int h = image.Shape().height; // image height

	// Create grayscale image used for Harris detection
	CFloatImage grayImage=ConvertToGray(image);

	// Apply a 7x7 gaussian blur to the grayscale image
	CFloatImage blurImage(w,h,1);
	Convolve(grayImage, blurImage, ConvolveKernel_7x7);

	// Transform matrices
	CTransform3x3 xform;
	CTransform3x3 trans1;
	CTransform3x3 rotate;
	CTransform3x3 scale;
	CTransform3x3 trans2;

	// Declare additional variables
	float pxl;					// pixel value
	double mean, sq_sum, stdev; // variables for normailizing data set

	// This image represents the window around the feature you need to compute to store as the feature descriptor
	const int windowSize = 8;
	CFloatImage destImage(windowSize, windowSize, 1);

	for (vector<Feature>::iterator i = features.begin(); i != features.end(); i++) {
		Feature &f = *i;

		// Compute the transform from each pixel in the 8x8 image to sample from the appropriate 
		// pixels in the 40x40 rotated window surrounding the feature
		trans1 = CTransform3x3::Translation(f.x, f.y);						// translate window to feature point
		rotate = CTransform3x3::Rotation(f.angleRadians * 180.0 / PI);		// rotate window by angle
		scale = CTransform3x3::Scale(5.0);									// scale window by 5
		trans2 = CTransform3x3::Translation(-windowSize/2, -windowSize/2);	// translate window to origin

		// transform resulting from combining above transforms
		xform = trans1*scale*rotate*trans2;

		//Call the Warp Global function to do the mapping
		WarpGlobal(blurImage, destImage, xform, eWarpInterpLinear);

		// Resize data field for a 8x8 square window
		f.data.resize(windowSize * windowSize);	

		// Find mean of window
		mean = 0;
		for (int y = 0; y < windowSize; y++) {
			for (int x = 0; x < windowSize; x++) {
				pxl = destImage.Pixel(x, y, 0);
				f.data[y*windowSize + x] = pxl;
				mean += pxl/(windowSize*windowSize);
			}
		}

		// Find standard deviation of window
		sq_sum = 0;
		for (int k = 0; k < windowSize*windowSize; k++) {
			sq_sum += (mean - f.data[k]) * (mean - f.data[k]);
		}
		stdev = sqrt(sq_sum/(windowSize*windowSize));

		// Normalize window to have 0 mean and unit variance by subtracting
		// by mean and dividing by standard deviation
		for (int k = 0; k < windowSize*windowSize; k++) {
			f.data[k] = (f.data[k]-mean)/stdev;
		}
	}
}