void ReadFile(CImage& img, const char* filename) { // Determine the file extension const char *dot = strrchr(filename, '.'); if (strcasecmp(dot, ".tga") == 0 || strcasecmp(dot, ".tga") == 0) { if ((&img.PixType()) == 0) img.ReAllocate(CShape(), typeid(uchar), sizeof(uchar), true); if (img.PixType() == typeid(uchar)) ReadFileTGA(*(CByteImage *) &img, filename); else { CByteImage imgAux; ReadFileTGA(imgAux, filename); if(img.PixType() == typeid(float)) TypeConvert(imgAux, *(CFloatImage*) &img); else throw CError("Cannot load image into img with this type of buffer"); } } else if (strcasecmp(dot, ".jpg") == 0 || strcasecmp(dot, ".jpeg") == 0) { if ((&img.PixType()) == 0) img.ReAllocate(CShape(), typeid(uchar), sizeof(uchar), true); if (img.PixType() == typeid(uchar)) ReadFileJPEG(*(CByteImage *) &img, filename); else { CByteImage imgAux; ReadFileJPEG(imgAux, filename); if(img.PixType() == typeid(float)) TypeConvert(imgAux, *(CFloatImage*) &img); else throw CError("Cannot load image into img with this type of buffer"); } } else throw CError("ReadFile(%s): file type not supported", filename); }
CByteImage HOGFeatureExtractor::render(const Feature& f) const { CShape cellShape = _oriMarkers[0].Shape(); CFloatImage hogImgF(CShape(cellShape.width * f.Shape().width, cellShape.height * f.Shape().height, 1)); hogImgF.ClearPixels(); float minBinValue, maxBinValue; f.getRangeOfValues(minBinValue, maxBinValue); // For every cell in the HOG for(int hi = 0; hi < f.Shape().height; hi++) { for(int hj = 0; hj < f.Shape().width; hj++) { // Now _oriMarkers, multiplying contribution by bin level for(int hc = 0; hc < _nAngularBins; hc++) { float v = f.Pixel(hj, hi, hc) / maxBinValue; for(int ci = 0; ci < cellShape.height; ci++) { float* cellIt = (float*) _oriMarkers[hc].PixelAddress(0, ci, 0); float* hogIt = (float*) hogImgF.PixelAddress(hj * cellShape.height, hi * cellShape.height + ci, 0); for(int cj = 0; cj < cellShape.width; cj++, hogIt++, cellIt++) { (*hogIt) += v * (*cellIt); } } } } } CByteImage hogImg; TypeConvert(hogImgF, hogImg); return hogImg; }
KernelInit::KernelInit() { static float k_11[2] = {0.5f, 0.5f}; static float k_121[3] = {0.25f, 0.5f, 0.25f}; static float k_14641[5] = {0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f}; static float k_8ptFP[8] = {-0.044734f, -0.059009f, 0.156544f, 0.449199f, 0.449199f, 0.156544f, -0.059009f, -0.044734f}; // The following are derived as fix-point /256 fractions of the above: // -12, -15, 40, 115 static float k_8ptI [8] = {-0.04687500f, -0.05859375f, 0.15625000f, 0.44921875f, 0.44921875f, 0.15625000f, -0.05859375f, -0.04687500f}; ConvolveKernel_121.ReAllocate(CShape(3, 1, 1), k_121, false, 3); ConvolveKernel_121.origin[0] = -1; ConvolveKernel_14641.ReAllocate(CShape(5, 1, 1), k_14641, false, 5); ConvolveKernel_14641.origin[0] = -2; ConvolveKernel_8tapLowPass.ReAllocate(CShape(8, 1, 1), k_8ptI, false, 8); ConvolveKernel_8tapLowPass.origin[0] = -4; }
cUFO::cUFO(double x, double y, TGame* game) : CMoveAbleObject(CShape( new CPrimaryShape(SHAPE_TYPE_OVAL, x + 44, y, 70, 60), new CPrimaryShape(SHAPE_TYPE_OVAL, x+0, y+50, 150, 50)), UFO, 250.0, 20.0, 0.0) { beamZone = new CPrimaryShape(SHAPE_TYPE_RECT, x, y + 100, 150, 50); this->game = game; this->setVelX(UFO_VELX); animation.setLastAnimationTime(SDL_GetTicks() - UFO_BEAM_TIME_DIFFERENCE); }
void Convolve(CImageOf<T> src, CImageOf<T>& dst, CFloatImage kernel, float scale, float offset) { // Determine the shape of the kernel and row buffer CShape kShape = kernel.Shape(); CShape sShape = src.Shape(); CShape bShape(sShape.width + kShape.width, kShape.height, sShape.nBands); int bWidth = bShape.width * bShape.nBands; // Allocate the result, if necessary, and the row buffer dst.ReAllocate(sShape, false); CFloatImage buffer(bShape); if (sShape.width * sShape.height * sShape.nBands == 0) return; CFloatImage output(CShape(sShape.width, 1, sShape.nBands)); // Fill up the row buffer initially for (int k = 0; k < kShape.height; k++) FillRowBuffer(&buffer.Pixel(0, k, 0), src, kernel, k, bWidth); // Determine if clipping is required // (we assume up-conversion to float never requires clipping, i.e., // floats have the highest dynamic range) T minVal = dst.MinVal(); T maxVal = dst.MaxVal(); if (minVal <= buffer.MinVal() && maxVal >= buffer.MaxVal()) minVal = maxVal = 0; // Process each row for (int y = 0; y < sShape.height; y++) { // Do the convolution ConvolveRow2D(buffer, kernel, &output.Pixel(0, 0, 0), sShape.width); // Scale, offset, and type convert ScaleAndOffsetLine(&output.Pixel(0, 0, 0), &dst.Pixel(0, y, 0), sShape.width * sShape.nBands, scale, offset, minVal, maxVal); // Shift up the row buffer and fill the last line if (y < sShape.height-1) { int k; for (k = 0; k < kShape.height-1; k++) memcpy(&buffer.Pixel(0, k, 0), &buffer.Pixel(0, k+1, 0), bWidth * sizeof(float)); FillRowBuffer(&buffer.Pixel(0, k, 0), src, kernel, y+k+1, bWidth); } } }
void MotionToColor(CFloatImage motim, CByteImage &colim, float maxmotion) { CShape sh = motim.Shape(); int width = sh.width, height = sh.height; colim.ReAllocate(CShape(width, height, 3)); int x, y; // determine motion range: float maxx = -999, maxy = -999; float minx = 999, miny = 999; float maxrad = -1; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { float fx = motim.Pixel(x, y, 0); float fy = motim.Pixel(x, y, 1); if (unknown_flow(fx, fy)) continue; maxx = __max(maxx, fx); maxy = __max(maxy, fy); minx = __min(minx, fx); miny = __min(miny, fy); float rad = sqrt(fx * fx + fy * fy); maxrad = __max(maxrad, rad); } } printf("max motion: %.4f motion range: u = %.3f .. %.3f; v = %.3f .. %.3f\n", maxrad, minx, maxx, miny, maxy); if (maxmotion > 0) // i.e., specified on commandline maxrad = maxmotion; if (maxrad == 0) // if flow == 0 everywhere maxrad = 1; if (verbose) fprintf(stderr, "normalizing by %g\n", maxrad); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { float fx = motim.Pixel(x, y, 0); float fy = motim.Pixel(x, y, 1); uchar *pix = &colim.Pixel(x, y, 0); if (unknown_flow(fx, fy)) { pix[0] = pix[1] = pix[2] = 0; } else { computeColor(fx/maxrad, fy/maxrad, pix); } } } }
void ReadFile (CImage& img, const char* filename) { // Determine the file extension char *dot = strrchr((char *) filename, '.'); if (strcmp(dot, ".tga") == 0 || strcmp(dot, ".tga") == 0) { if ((&img.PixType()) == 0) img.ReAllocate(CShape(), typeid(uchar), sizeof(uchar), true); if (img.PixType() == typeid(uchar)) ReadFileTGA(*(CByteImage *) &img, filename); else throw CError("ReadFile(%s): haven't implemented conversions yet", filename); } else throw CError("ReadFile(%s): file type not supported", filename); }
KernelInit::KernelInit() { static float k_11[2] = {0.5f, 0.5f}; static float k_121[3] = {0.25f, 0.5f, 0.25f}; static float k_14641[5] = {0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f}; static float k_8ptFP[8] = {-0.044734f, -0.059009f, 0.156544f, 0.449199f, 0.449199f, 0.156544f, -0.059009f, -0.044734f}; // The following are derived as fix-point /256 fractions of the above: // -12, -15, 40, 115 static float k_8ptI [8] = {-0.04687500f, -0.05859375f, 0.15625000f, 0.44921875f, 0.44921875f, 0.15625000f, -0.05859375f, -0.04687500f}; static float k_7x7[49] = { 1.0, 4.0, 7.0, 10.0, 7.0, 4.0, 1.0, 4.0, 12.0, 26.0, 33.0, 26.0, 12.0, 4.0, 7.0, 26.0, 55.0, 71.0, 55.0, 26.0, 7.0, 10.0, 33.0, 71.0, 91.0, 71.0, 33.0, 10.0, 7.0, 26.0, 55.0, 71.0, 55.0, 26.0, 7.0, 4.0, 12.0, 26.0, 33.0, 26.0, 12.0, 4.0, 1.0, 4.0, 7.0, 10.0, 7.0, 4.0, 1.0 }; for (int i = 0; i < 49; i++) { k_7x7[i] /= 1115.0; } ConvolveKernel_121.ReAllocate(CShape(3, 1, 1), k_121, false, 3); ConvolveKernel_121.origin[0] = 1; ConvolveKernel_14641.ReAllocate(CShape(5, 1, 1), k_14641, false, 5); ConvolveKernel_14641.origin[0] = 2; ConvolveKernel_8tapLowPass.ReAllocate(CShape(8, 1, 1), k_8ptI, false, 8); ConvolveKernel_8tapLowPass.origin[0] = 4; ConvolveKernel_7x7.ReAllocate(CShape(7, 7, 1), k_7x7, false, 7); /* Sobel filters */ static float k_SobelX[9] = { -1, 0, 1, -2, 0, 2, -1, 0, 1 }; static float k_SobelY[9] = { -1, -2, -1, 0, 0, 0, 1, 2, 1 }; ConvolveKernel_SobelX.ReAllocate(CShape(3, 3, 1), k_SobelX, false, 3); ConvolveKernel_SobelX.origin[0] = 1; ConvolveKernel_SobelX.origin[1] = 1; ConvolveKernel_SobelY.ReAllocate(CShape(3, 3, 1), k_SobelY, false, 3); ConvolveKernel_SobelY.origin[0] = 1; ConvolveKernel_SobelY.origin[1] = 1; }
void SupportVectorMachine::predictSlidingWindow(const Feature &feat, CFloatImage &response) const { response.ReAllocate(CShape(feat.Shape().width, feat.Shape().height, 1)); response.ClearPixels(); /******** BEGIN TODO ********/ // Sliding window prediction. // // In this project we are using a linear SVM. This means that // it's classification function is very simple, consisting of a // dot product of the feature vector with a set of weights learned // during training, followed by a subtraction of a bias term // // pred <- dot(feat, weights) - bias term // // Now this is very simple to compute when we are dealing with // cropped images, our computed features have the same dimensions // as the SVM weights. Things get a little more tricky when you // want to evaluate this function over all possible subwindows of // a larger feature, one that we would get by running our feature // extraction on an entire image. // // Here you will evaluate the above expression by breaking // the dot product into a series of convolutions (remember that // a convolution can be though of as a point wise dot product with // the convolution kernel), each one with a different band. // // Convolve each band of the SVM weights with the corresponding // band in feat, and add the resulting score image. The final // step is to subtract the SVM bias term given by this->getBiasTerm(). // // Hint: you might need to set the origin for the convolution kernel // in order to get the result from convoltion to be correctly centered // // Useful functions: // Convolve, BandSelect, this->getWeights(), this->getBiasTerm() Feature weights = this->getWeights(); int nWtBands = weights.Shape().nBands; // Set the center of the window as the origin for the conv. kernel for (int band = 0; band < nWtBands; band++) { // Select a band CFloatImage featBand; CFloatImage weightBand; BandSelect(feat, featBand, band, 0); BandSelect(weights, weightBand, band, 0); // Set the origin of the kernel weightBand.origin[0] = weights.Shape().width / 2; weightBand.origin[1] = weights.Shape().height / 2; // Compute the dot product CFloatImage dotproduct; dotproduct.ClearPixels(); Convolve(featBand, dotproduct, weightBand); // Add the resulting score image for (int y = 0; y < feat.Shape().height; y++) { for (int x = 0; x < feat.Shape().width; x++) { response.Pixel(x, y, 0) += dotproduct.Pixel(x, y, 0); } // End of x loop } // End of y loop } // End of band loop // Substract the SVM bias term for (int y = 0; y < feat.Shape().height; y++) { for (int x = 0; x < feat.Shape().width; x++) { response.Pixel(x, y, 0) -= this->getBiasTerm(); } // End of x loop } // End of y loop /******** END TODO ********/ }
void CImage::DeAllocate() { // Release the memory & set to default values ReAllocate(CShape(), *(const type_info *) 0, 0, 0, false, 0); SetDefaults(); }
CFloatImage SupportVectorMachine::predictSlidingWindow(const Feature& feat) const { CFloatImage score(CShape(feat.Shape().width,feat.Shape().height,1)); score.ClearPixels(); /******** BEGIN TODO ********/ // Sliding window prediction. // // In this project we are using a linear SVM. This means that // it's classification function is very simple, consisting of a // dot product of the feature vector with a set of weights learned // during training, followed by a subtraction of a bias term // // pred <- dot(feat, weights) - bias term // // Now this is very simple to compute when we are dealing with // cropped images, our computed features have the same dimensions // as the SVM weights. Things get a little more tricky when you // want to evaluate this function over all possible subwindows of // a larger feature, one that we would get by running our feature // extraction on an entire image. // // Here you will evaluate the above expression by breaking // the dot product into a series of convolutions (remember that // a convolution can be though of as a point wise dot product with // the convolution kernel), each one with a different band. // // Convolve each band of the SVM weights with the corresponding // band in feat, and add the resulting score image. The final // step is to subtract the SVM bias term given by this->getBiasTerm(). // // Hint: you might need to set the origin for the convolution kernel // in order to get the result from convoltion to be correctly centered // // Useful functions: // Convolve, BandSelect, this->getWeights(), this->getBiasTerm() //printf("TODO: SupportVectorMachine.cpp:273\n"); exit(EXIT_FAILURE); Feature weights = getWeights(); for (int b=0; b<feat.Shape().nBands; b++){ CFloatImage currentBandWeights = CFloatImage(weights.Shape().width, weights.Shape().height, 1); CFloatImage currentBandFeatures = CFloatImage(feat.Shape().width, feat.Shape().height, 1); CFloatImage convolved = CFloatImage(CShape(feat.Shape().width, feat.Shape().height, 1)); CFloatImage final(CShape(feat.Shape().width, feat.Shape().height, 1)); BandSelect(weights, currentBandWeights, b, 0); BandSelect(feat, currentBandFeatures, b, 0); currentBandWeights.origin[0] = weights.origin[0]; currentBandWeights.origin[1] = weights.origin[1]; Convolve(feat, convolved, currentBandWeights); BandSelect(convolved, final, b, 0); try{ score += final; } catch (CError err) { printf("OH NOES: the final chapter!"); } } score-=getBiasTerm(); /******** END TODO ********/ return score; }
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 } }
/******************* 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; }