void ConvolveRow(CImageOf<T> buffer, CFloatImage kernel, T* dst, int n, T minVal, T maxVal) { CShape kShape = kernel.Shape(); int kX = kShape.width; int kY = kShape.height; CShape bShape = buffer.Shape(); int nB = bShape.nBands; for (int i = 0; i < n; i++) { for (int b = 0; b < nB; b++) { float sum = 0.0f; for (int k = 0; k < kY; k++) { float* kPtr = &kernel.Pixel(0, k, 0); T* bPtr = &buffer.Pixel(i, k, b); for (int l = 0; l < kX; l++, bPtr += nB) sum += kPtr[l] * bPtr[0]; } *dst++ = (T) __max(minVal, __min(maxVal, sum)); } } }
/******************* TO DO 5 ********************* * NormalizeBlend: * INPUT: * acc: input image whose alpha channel (4th channel) contains * normalizing weight values * img: where output image will be stored * OUTPUT: * normalize r,g,b values (first 3 channels) of acc and store it into img */ static void NormalizeBlend(CFloatImage& acc, CByteImage& img) { // *** BEGIN TODO *** // fill in this routine.. int width = acc.Shape().width; int height = acc.Shape().height; for (int i=0;i<width;i++){ for (int j=0;j<height;j++){ float w = acc.Pixel(i,j,3); img.Pixel(i,j,3) = 255; if (w > 0){ img.Pixel(i,j,0) = acc.Pixel(i,j,0) / w; img.Pixel(i,j,1) = acc.Pixel(i,j,1) / w; img.Pixel(i,j,2) = acc.Pixel(i,j,2) / w; } else { img.Pixel(i,j,0) = 0; img.Pixel(i,j,1) = 0; img.Pixel(i,j,2) = 0; } } } // *** END TODO *** }
static void ConvolveRow2D(CFloatImage& buffer, CFloatImage& kernel, float dst[], int n) { CShape kShape = kernel.Shape(); int kX = kShape.width; int kY = kShape.height; CShape bShape = buffer.Shape(); int nB = bShape.nBands; for (int i = 0; i < n; i++) { for (int b = 0; b < nB; b++) { float sum = 0.0f; for (int k = 0; k < kY; k++) { float* kPtr = &kernel.Pixel(0, k, 0); float* bPtr = &buffer.Pixel(i, k, b); for (int l = 0; l < kX; l++, bPtr += nB) sum += kPtr[l] * bPtr[0]; } *dst++ = sum; } } }
void Convolve(CImageOf<T> src, CImageOf<T>& dst, CFloatImage kernel) { // Determine the shape of the kernel and source image CShape kShape = kernel.Shape(); CShape sShape = src.Shape(); // Allocate the result, if necessary dst.ReAllocate(sShape, false); if (sShape.width * sShape.height * sShape.nBands == 0) return; // Do the convolution for (int y = 0; y < sShape.height; y++) for (int x = 0; x < sShape.width; x++) for (int c = 0; c < sShape.nBands; c++) { double sum = 0; for (int kx = 0; kx < kShape.width; kx++) for (int ky = 0; ky < kShape.height; ky++) if ((x-kernel.origin[0]+kx >= 0) && (x-kernel.origin[0]+kx < sShape.width) && (y-kernel.origin[1]+ky >= 0) && (y-kernel.origin[1]+ky < sShape.height)) sum += kernel.Pixel(kx,ky,0) * src.Pixel(x-kernel.origin[0]+kx,y-kernel.origin[1]+ky,c); dst.Pixel(x,y,c) = (T) __max(dst.MinVal(), __min(dst.MaxVal(), sum)); } }
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"); } }
// Convert CFloatImage to CByteImage. void convertToByteImage(CFloatImage &floatImage, CByteImage &byteImage) { CShape sh = floatImage.Shape(); //printf("%d\n", floatImage.Shape().nBands); //printf("%d\n", byteImage.Shape().nBands); assert(floatImage.Shape().nBands == min(byteImage.Shape().nBands, 3)); for (int y=0; y<sh.height; y++) { for (int x=0; x<sh.width; x++) { for (int c=0; c<sh.nBands; c++) { float value = floor(255*floatImage.Pixel(x,y,c) + 0.5f); if (value < byteImage.MinVal()) { value = byteImage.MinVal(); } else if (value > byteImage.MaxVal()) { value = byteImage.MaxVal(); } // We have to flip the image and reverse the color // channels to get it to come out right. How silly! byteImage.Pixel(x,sh.height-y-1,sh.nBands-c-1) = (uchar) value; } } } }
// convert float disparity image into a color image using jet colormap void float2color(CFloatImage fimg, CByteImage &img, float dmin, float dmax) { CShape sh = fimg.Shape(); int width = sh.width, height = sh.height; sh.nBands = 3; img.ReAllocate(sh); float scale = 1.0 / (dmax - dmin); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float f = fimg.Pixel(x, y, 0); int r = 0; int g = 0; int b = 0; if (f != INFINITY) { float val = scale * (f - dmin); jet(val, r, g, b); } img.Pixel(x, y, 0) = b; img.Pixel(x, y, 1) = g; img.Pixel(x, y, 2) = r; } } }
// Compute silly example features. This doesn't do anything // meaningful, but may be useful to use as an example. void dummyComputeFeatures(CFloatImage &image, FeatureSet &features) { CShape sh = image.Shape(); Feature f; for (int y=0; y<sh.height; y++) { for (int x=0; x<sh.width; x++) { double r = image.Pixel(x,y,0); double g = image.Pixel(x,y,1); double b = image.Pixel(x,y,2); if ((int)(255*(r+g+b)+0.5) % 100 == 1) { // If the pixel satisfies this meaningless criterion, // make it a feature. f.type = 1; f.id += 1; f.x = x; f.y = y; f.data.resize(1); f.data[0] = r + g + b; features.push_back(f); } } } }
//TO DO--------------------------------------------------------------------- //Loop through the image to compute the harris corner values as described in class // srcImage: grayscale of original image // harrisImage: populate the harris values per pixel in this image void computeHarrisValues(CFloatImage &srcImage, CFloatImage &harrisImage) { int h = srcImage.Shape().height; int w = srcImage.Shape().width; CFloatImage A(srcImage.Shape()); CFloatImage B(srcImage.Shape()); CFloatImage C(srcImage.Shape()); GetHarrisComponents(srcImage, A, B, C); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { double determinant = A.Pixel(x, y, 0) * C.Pixel(x, y, 0) - B.Pixel(x, y, 0)* B.Pixel(x, y, 0); double trace = A.Pixel(x, y, 0) + C.Pixel(x, y, 0); float *pixel = &harrisImage.Pixel(x, y, 0); if (trace == 0) { *pixel = 0; } else { *pixel = determinant / trace; } } } }
void ComputeHarrisFeatures(CFloatImage &image, FeatureSet &features) { //Create grayscale image used for Harris detection CFloatImage grayImage=ConvertToGray(image); //Create image to store Harris values CFloatImage harrisImage(image.Shape().width,image.Shape().height,1); //Create image to store local maximum harris values as 1, other pixels 0 CByteImage harrisMaxImage(image.Shape().width,image.Shape().height,1); //compute Harris values puts harris values at each pixel position in harrisImage. //You'll need to implement this function. computeHarrisValues(grayImage, harrisImage); // Threshold the harris image and compute local maxima. You'll need to implement this function. computeLocalMaxima(harrisImage,harrisMaxImage); // Prints out the harris image for debugging purposes CByteImage tmp(harrisImage.Shape()); convertToByteImage(harrisImage, tmp); WriteFile(tmp, "harris.tga"); // TO DO-------------------------------------------------------------------- //Loop through feature points in harrisMaxImage and fill in information needed for //descriptor computation for each point above a threshold. We fill in id, type, //x, y, and angle. CFloatImage A(grayImage.Shape()); CFloatImage B(grayImage.Shape()); CFloatImage C(grayImage.Shape()); CFloatImage partialX(grayImage.Shape()); CFloatImage partialY(grayImage.Shape()); GetHarrisComponents(grayImage, A, B, C, &partialX, &partialY); int featureCount = 0; for (int y=0;y<harrisMaxImage.Shape().height;y++) { for (int x=0;x<harrisMaxImage.Shape().width;x++) { // Skip over non-maxima if (harrisMaxImage.Pixel(x, y, 0) == 0) continue; //TO DO--------------------------------------------------------------------- // Fill in feature with descriptor data here. Feature f; f.type = 2; f.id = featureCount++; f.x = x; f.y = y; f.angleRadians = GetCanonicalOrientation(x, y, A, B, C, partialX, partialY); //atan(partialY.Pixel(x, y, 0)/partialX.Pixel(x, y, 0)); // Add the feature to the list of features features.push_back(f); } } }
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 ConvolveSeparable(CImageOf<T> src, CImageOf<T>& dst, CFloatImage x_kernel, CFloatImage y_kernel, float scale, float offset, int decimate, int interpolate) { // Allocate the result, if necessary CShape dShape = src.Shape(); if (decimate > 1) { dShape.width = (dShape.width + decimate-1) / decimate; dShape.height = (dShape.height + decimate-1) / decimate; } dst.ReAllocate(dShape, false); // Allocate the intermediate images CImageOf<T> tmpImg1(src.Shape()); CImageOf<T> tmpImg2(src.Shape()); // Create a proper vertical convolution kernel CFloatImage v_kernel(1, y_kernel.Shape().width, 1); for (int k = 0; k < y_kernel.Shape().width; k++) v_kernel.Pixel(0, k, 0) = y_kernel.Pixel(k, 0, 0); v_kernel.origin[1] = y_kernel.origin[0]; // Perform the two convolutions Convolve(src, tmpImg1, x_kernel, 1.0f, 0.0f); Convolve(tmpImg1, tmpImg2, v_kernel, scale, offset); // Downsample or copy for (int y = 0; y < dShape.height; y++) { T* sPtr = &tmpImg2.Pixel(0, y * decimate, 0); T* dPtr = &dst.Pixel(0, y, 0); int nB = dShape.nBands; for (int x = 0; x < dShape.width; x++) { for (int b = 0; b < nB; b++) dPtr[b] = sPtr[b]; sPtr += decimate * nB; dPtr += nB; } } interpolate++; // to get rid of "unused parameter" warning }
// get min and max (non-INF) values void getMinMax(CFloatImage fimg, float& vmin, float& vmax) { CShape sh = fimg.Shape(); int width = sh.width, height = sh.height; vmin = INFINITY; vmax = -INFINITY; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float f = fimg.Pixel(x, y, 0); if (f == INFINITY) continue; vmin = min(f, vmin); vmax = max(f, vmax); } } }
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; }
//Loop through the image to determine suitable feature points // srcImage: image with Harris values // destImage: Assign 1 to local maximum in 3x3 window that are above a given // threshold, 0 otherwise void computeLocalMaxima(CFloatImage &srcImage,CByteImage &destImage) { int w = srcImage.Shape().width; // image width int h = srcImage.Shape().height; // image height //float threshold = .024; float threshold = .01; // threshold value for identifying features // Declare additional variables float max; // harris value to check as local max int newX, newY; // (x,y) coordinate for pixel in 5x5 sliding window int j; // int for iterating through 5x5 window // Loop through 'srcImage' and determine suitable feature points that // fit the following criteria: // - harris value c is greater than a predefined threshold // - c is a local maximum in a 5x5 neighborhood for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { max = srcImage.Pixel(x,y,0); // If harris value is greater than a predefined threshold check // if value is a local maximum in a 5x5 neighborhood. if (max > threshold) { for (j = 0; j < 25; j++) { find5x5Index(x,y,j,&newX,&newY); if(srcImage.Shape().InBounds(newX, newY) && srcImage.Pixel(newX, newY, 0) > max) { destImage.Pixel(x,y,0) = 0; break; } } if (j != 25) continue; destImage.Pixel(x,y,0) = 1; } else { destImage.Pixel(x,y,0) = 0; } } } }
void ConvolveSeparable(CImageOf<T> src, CImageOf<T>& dst, CFloatImage x_kernel, CFloatImage y_kernel, int subsample) { // Allocate the result, if necessary CShape dShape = src.Shape(); if (subsample > 1) { dShape.width = (dShape.width + subsample-1) / subsample; dShape.height = (dShape.height + subsample-1) / subsample; } dst.ReAllocate(dShape, false); // Allocate the intermediate images CImageOf<T> tmpImg1(src.Shape()); CImageOf<T> tmpImg2(src.Shape()); // Create a proper vertical convolution kernel CFloatImage v_kernel(1, y_kernel.Shape().width, 1); for (int k = 0; k < y_kernel.Shape().width; k++) v_kernel.Pixel(0, k, 0) = y_kernel.Pixel(k, 0, 0); v_kernel.origin[1] = y_kernel.origin[0]; // Perform the two convolutions Convolve(src, tmpImg1, x_kernel); Convolve(tmpImg1, tmpImg2, v_kernel); // Downsample or copy for (int y = 0; y < dShape.height; y++) { T* sPtr = &tmpImg2.Pixel(0, y * subsample, 0); T* dPtr = &dst.Pixel(0, y, 0); int nB = dShape.nBands; for (int x = 0; x < dShape.width; x++) { for (int b = 0; b < nB; b++) dPtr[b] = sPtr[b]; sPtr += subsample * nB; dPtr += nB; } } }
CFloatImage GetXWindowAroundPixel(CFloatImage srcImage, int x, int y, int size) { float *matrix = new float[size * size]; for(int row=(y-(size-1)/2); row<=(y+(size-1)/2); row++) { for(int col=(x-(size-1)/2);col<=(x+(size-1)/2);col++) { if(row<0 || row>=srcImage.Shape().height || col<0 || col>=srcImage.Shape().width) { matrix[(row-(y-(size-1)/2))*size + (col-(x-(size-1)/2))] = 0.; } else { matrix[(row-(y-(size-1)/2))*size + (col-(x-(size-1)/2))] = srcImage.Pixel(col, row, 0); } } } return GetImageFromMatrix(matrix, size, size); }
// Convert Fl_Image to CFloatImage. bool convertImage(const Fl_Image *image, CFloatImage &convertedImage) { if (image == NULL) { return false; } // Let's not handle indexed color images. if (image->count() != 1) { return false; } int w = image->w(); int h = image->h(); int d = image->d(); // Get the image data. const char *const *data = image->data(); int index = 0; for (int y=0; y<h; y++) { for (int x=0; x<w; x++) { if (d < 3) { // If there are fewer than 3 channels, just use the // first one for all colors. convertedImage.Pixel(x,y,0) = ((uchar) data[0][index]) / 255.0f; convertedImage.Pixel(x,y,1) = ((uchar) data[0][index]) / 255.0f; convertedImage.Pixel(x,y,2) = ((uchar) data[0][index]) / 255.0f; } else { // Otherwise, use the first 3. convertedImage.Pixel(x,y,0) = ((uchar) data[0][index]) / 255.0f; convertedImage.Pixel(x,y,1) = ((uchar) data[0][index+1]) / 255.0f; convertedImage.Pixel(x,y,2) = ((uchar) data[0][index+2]) / 255.0f; } index += d; } } return true; }
void featuresFromImage(Feature* f, CFloatImage img, int width, int height) { vector<double, std::allocator<double>>::iterator it; f->data.clear(); for(int y=0; y<height; y++) { for(int x=0; x<width; x++) { f->data.push_back(img.Pixel(x,y,0)); } } }
/******************* TO DO 5 ********************* * NormalizeBlend: * INPUT: * acc: input image whose alpha channel (4th channel) contains * normalizing weight values * img: where output image will be stored * OUTPUT: * normalize r,g,b values (first 3 channels) of acc and store it into img */ static void NormalizeBlend(CFloatImage& acc, CByteImage& img) { // BEGIN TODO // fill in this routine.. // divide the total weight for every pixel CShape shacc=acc.Shape(); int widthacc=shacc.width; int heightacc=shacc.height; for (int ii=0;ii<widthacc;ii++) { for (int jj=0;jj<heightacc;jj++) { if (acc.Pixel(ii,jj,3)>0) { img.Pixel(ii,jj,0)=(int)(acc.Pixel(ii,jj,0)/acc.Pixel(ii,jj,3)); img.Pixel(ii,jj,1)=(int)(acc.Pixel(ii,jj,1)/acc.Pixel(ii,jj,3)); img.Pixel(ii,jj,2)=(int)(acc.Pixel(ii,jj,2)/acc.Pixel(ii,jj,3)); } else { img.Pixel(ii,jj,0)=0; img.Pixel(ii,jj,1)=0; img.Pixel(ii,jj,2)=0; } } } // END TODO }
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); } } }
double GetCanonicalOrientation(int x, int y, CFloatImage A, CFloatImage B, CFloatImage C, CFloatImage partialX, CFloatImage partialY) { float aPixel = A.Pixel(x, y, 0); float bPixel = B.Pixel(x, y, 0); float cPixel = C.Pixel(x, y, 0); /*double a = 1; double b = -(aPixel+cPixel); double c = (aPixel * cPixel - pow((double)bPixel, 2.));*/ //double lambda = (- b + sqrt(pow((double)b, 2.) - 4.*a*c)) / (2.*a); double lambda = 1./2. *((aPixel+cPixel) + sqrt(4.*pow((double)bPixel,2.) + pow(((double)aPixel - cPixel), 2.))); double yComponent = aPixel - lambda - bPixel; double xComponent = cPixel - lambda - bPixel; /*y = -b x = a - lambd */ if (xComponent == 0.) { return (partialY.Pixel(x, y, 0) > 0)? PI/2. : -PI/2.; } double first = aPixel*xComponent + bPixel*yComponent; double second = bPixel*xComponent + cPixel*yComponent; double first_precision = pow((first -lambda * xComponent), 2.); double second_precision = pow((second - lambda * yComponent), 2.); //Sanity check for eigenvalues: this confirms our given eigenvalue is //computed correctly if (first_precision > .0000001 || second_precision > .0000001 ) { int z = 3; } return (partialX.Pixel(x, y, 0) > 0)? atan(-bPixel/(aPixel-lambda)) : atan(-bPixel/(aPixel-lambda)) + PI; //return (partialX.Pixel(x, y, 0) > 0)? atan(yComponent/xComponent) : atan(yComponent/xComponent) + PI; }
void WarpLocal(CImageOf<T> src, CImageOf<T>& dst, CFloatImage uv, bool relativeCoords, EWarpInterpolationMode interp, float cubicA) { // Check that dst is of the right shape CShape sh(uv.Shape().width, uv.Shape().height, src.Shape().nBands); dst.ReAllocate(sh); // Allocate a row buffer for coordinates int n = sh.width; std::vector<float> rowBuf; rowBuf.resize(n*2); // Precompute the cubic interpolant if (interp == eWarpInterpCubic) InitializeCubicLUT(cubicA); // Process each row for (int y = 0; y < sh.height; y++) { float *uvP = &uv .Pixel(0, y, 0); float *xyP = (relativeCoords) ? &rowBuf[0] : uvP; T *dstP = &dst.Pixel(0, y, 0); // Convert to absolute coordinates if necessary if (relativeCoords) { for (int x = 0; x < n; x++) { xyP[2*x+0] = x + uvP[2*x+0]; xyP[2*x+1] = y + uvP[2*x+1]; } } // Resample the line WarpLine(src, dstP, xyP, n, sh.nBands, interp, src.MinVal(), src.MaxVal()); } }
cv::Mat FlowIOOpenCVWrapper::read(std::string path) { CFloatImage flow; ReadFlowFile(flow, path.c_str()); int rows = flow.Shape().height; int cols = flow.Shape().width; assert(rows > 0); assert(cols > 0); assert(flow.Shape().nBands == 2); cv::Mat matFlow(rows, cols, CV_32FC2, cv::Scalar(0, 0)); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { matFlow.at<cv::Vec2f>(i, j)[0] = flow.Pixel(j, i, 0); matFlow.at<cv::Vec2f>(i, j)[1] = flow.Pixel(j, i, 1); } } return matFlow; }
bool isLocalMax(CFloatImage srcImage, int x, int y) { int width = srcImage.Shape().width; int height = srcImage.Shape().height; float centerPixel = srcImage.Pixel(x, y, 0); for (int row = 0; row < 5; row++) { for (int col = 0; col < 5; col++) { int xOffset = x - 2 + col; int yOffset = y - 2 + row; if (xOffset == x && yOffset == y) { continue; } float pixelAtOffset; if (xOffset < 0 || yOffset < 0 || xOffset >= width || yOffset >= height) { pixelAtOffset = 0.; } else { pixelAtOffset = srcImage.Pixel(xOffset, yOffset, 0); } if (pixelAtOffset >= centerPixel) { return false; } } } return true; }
void subsample(Feature* f, int imgSize, CFloatImage gaussianImage) { vector<double, std::allocator<double>>::iterator it; 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%2 == 0 || y%2 == 0) { f->data.erase(f->data.begin() + count); } else { count++; } } } }
// Compute features using Harris corner detection method void ComputeHarrisFeatures(CFloatImage &image, FeatureSet &features) { // Create grayscale image used for Harris detection CFloatImage grayImage = ConvertToGray(image); // Create image to store Harris values CFloatImage harrisImage(image.Shape().width,image.Shape().height,1); // Create image to store local maximum harris values as 1, other pixels 0 CByteImage harrisMaxImage(image.Shape().width,image.Shape().height,1); // Create image to store orientation values CFloatImage orientationImage(image.Shape().width, image.Shape().height, 1); // Compute the harris score at each pixel position, storing the result in in harrisImage. computeHarrisValues(grayImage, harrisImage, orientationImage); // Threshold the harris image and compute local maxima. computeLocalMaxima(harrisImage,harrisMaxImage); // Save images CByteImage tmp(harrisImage.Shape()); CByteImage tmp2(harrisImage.Shape()); convertToByteImage(harrisImage, tmp); convertToByteImage(grayImage, tmp2); WriteFile(tmp2, "grayImg.tga"); WriteFile(tmp, "harris.tga"); WriteFile(harrisMaxImage, "harrisMax.tga"); // Loop through feature points in harrisMaxImage and fill in id, type, x, y, and angle // information needed for descriptor computation for each feature point, then add them // to feature set int id = 0; for (int y=0; y < harrisMaxImage.Shape().height; y++) { for (int x=0; x < harrisMaxImage.Shape().width; x++) { if (harrisMaxImage.Pixel(x, y, 0) == 1) { Feature f; f.id = id; f.type = 2; f.x = x; f.y = y; f.angleRadians = orientationImage.Pixel(x,y,0); features.push_back(f); id++; } } } }
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; }
// TO DO--------------------------------------------------------------------- // Loop through the harrisImage to threshold and compute the local maxima in a neighborhood // srcImage: image with Harris values // destImage: Assign 1 to a pixel if it is above a threshold and is the local maximum in 3x3 window, 0 otherwise. // You'll need to find a good threshold to use. void computeLocalMaxima(CFloatImage &srcImage,CByteImage &destImage) { int width = srcImage.Shape().width; int height = srcImage.Shape().height; double mean, stdDev; double sum = 0; double squareSum = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float pixel = srcImage.Pixel(x, y, 0); if (!(pixel >= 0 || pixel < 0)) { auto error = "TRUE"; } sum += srcImage.Pixel(x, y, 0); } } mean = sum / (float)(width * height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { squareSum += pow((srcImage.Pixel(x, y, 0) - mean), 2.); } } stdDev = sqrt(squareSum / (float)(width * height - 1)); int count = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { unsigned char *pixel = &destImage.Pixel(x, y, 0); if (srcImage.Pixel(x, y, 0) >= 3.*stdDev + mean && isLocalMax(srcImage, x, y)) { count++; *pixel = 1; } else { *pixel = 0; } } } }
void makeNonoccMask(CFloatImage disp0, CFloatImage disp0y, CFloatImage disp1, int dir, float thresh, CByteImage &mask) { CShape sh = disp0.Shape(); int width = sh.width, height = sh.height; if (sh != disp1.Shape()) throw CError("shapes differ"); int ydisps = (sh == disp0y.Shape()); mask.ReAllocate(sh); mask.ClearPixels(); int x, y; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { float dx = disp0.Pixel(x, y, 0); float dy = (ydisps ? disp0y.Pixel(x, y, 0) : 0.0); if (dx == INFINITY) // unknown continue; mask.Pixel(x, y, 0) = 128; // occluded // find nonocc int x1 = (int)round(x + dir * dx); int y1 = (int)round(y + dy); if (x1 < 0 || x1 >= width || y1 < 0 || y1 >= height) continue; float dx1 = disp1.Pixel(x1, y1, 0); float diff = dx - dx1; if (fabs(diff) > thresh) continue; // fails cross checking -- occluded mask.Pixel(x, y, 0) = 255; // cross-checking OK } } }