www.pudn.com > ---StereoMatch.rar > BoxFilter.cpp
/////////////////////////////////////////////////////////////////////////// // // NAME // BoxFilter.cpp -- separable box filter (moving average convolution) // // DESIGN NOTES // Two different versions with different computation inner loops and // memory access patterns are implemented. See comments below. // // SEE ALSO // BoxFilter.h longer description of the interface // // Copyright © Daniel Scharstein and Richard Szeliski, 2001. // See Copyright.h for more details // /////////////////////////////////////////////////////////////////////////// #include "Image.h" #include "Error.h" #include "Convert.h" #include "BoxFilter.h" #include#include static int borderIndex(int index, int len, EBorderMode m) { // TODO: this code is common with Convolve.cpp: should be merged... // returns correct index depending on border mode // cannot be used with eBorderZero since it returns index, not value if (index < 0) { assert(-index < len); // "double" wrapping not supported switch (m) { case eBorderReplicate: return 0; case eBorderReflect: return -index; case eBorderCyclic: return index+len; default: throw CError("borderIndex: bad borderMode"); } } else if (index >= len) { assert(len+len-index >= 2); // "double" wrapping not supported switch (m) { case eBorderReplicate: return len-1; case eBorderReflect: return len+len-index-2; case eBorderCyclic: return index-len; default: throw CError("borderIndex: bad borderMode"); } } else return index; } /////////////////////////////////////////////////////////////////////////// // box filter functions template static void boxFilterLines(T* src, T* dst, int n_sums, int len, int stride, int w, int pl, int pr, EBorderMode borderMode, bool average) { // Box filter multiple rows or columns of an image // w - window width (e.g., 5) // pl - offset to first cell to left of window (e.g., -3) // pr - offset to last cell in window (e.g., 2) // src - pointer to original data // dst - pointer to result // n_sums - number of running sums to be kept // len - length of each row or column // stride - distance between elements in line // average- compute an average int i, k, x, rx; T scale = (T)((average) ? 1.0 / w : 1); // factor for computing average // compute first value (x==0) for (k=0; k extern void BoxFilter(CImageOf & src, CImageOf & dst, int xWidth, int yWidth, bool average) { // Box filter operation // second version - operates in memory order to avoid swapping if (xWidth != yWidth) throw CError("BoxFilter: xWidth != yWidth not implemented yet"); CShape sh = src.Shape(); int width = sh.width, height = sh.height, n_bands = sh.nBands; dst.ReAllocate(sh, false); // allocate memory for copy of src CImageOf tmp; tmp.ReAllocate(sh); // allocate memory for copy of src tmp.borderMode = src.borderMode; int w = xWidth; // window size (e.g., 5) int pr = w / 2; // pointer to right (e.g., 2): value to add int pl = pr - w; // pointer to left (e.g., -3): value to subtract // aggregate each row, all disparity levels in parallel for (int y = 0; y < height; y++) { T* src_row = &src.Pixel(0, y, 0); T* dst_row = &tmp.Pixel(0, y, 0); boxFilterLines(src_row, dst_row, n_bands, width, n_bands, w, pl, pr, src.borderMode, average); } // aggregate all columns at all disparity levels in parallel // compute vertical stride int stride = &dst.Pixel(0, 1, 0) - &src.Pixel(0, 0, 0); int stride2 = &tmp.Pixel(0, 1, 0) - &tmp.Pixel(0, 0, 0); assert(stride == stride2); T* src_cols = &tmp.Pixel(0, 0, 0); T* dst_cols = &dst.Pixel(0, 0, 0); boxFilterLines(src_cols, dst_cols, n_bands*width, height, stride, w, pl, pr, dst.borderMode, average); } extern void BoxFilter(CByteImage& src, CByteImage& dst, int xWidth, int yWidth, bool average) { // Need to use an integer accumulator for precision CIntImage tmp(src.Shape()); CopyPixels(src, tmp); BoxFilter(tmp, tmp, xWidth, yWidth, average); dst.ReAllocate(src.Shape(), false); CopyPixels(tmp, dst); } extern void CallBoxFilters(void) { CByteImage bimg; BoxFilter(bimg, bimg, 5, 5, false); CIntImage iimg; BoxFilter(iimg, iimg, 5, 5, false); CFloatImage fimg; BoxFilter(fimg, fimg, 5, 5, false); }