libidx
/home/rex/ebltrunk/core/libidx/include/padder.hpp
00001 /***************************************************************************
00002  *   Copyright (C) 2011 by Pierre Sermanet *
00003  *   pierre.sermanet@gmail.com *
00004  *   All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Redistribution under a license not approved by the Open Source
00014  *       Initiative (http://www.opensource.org) must display the
00015  *       following acknowledgement in all advertising material:
00016  *        This product includes software developed at the Courant
00017  *        Institute of Mathematical Sciences (http://cims.nyu.edu).
00018  *     * The names of the authors may not be used to endorse or promote products
00019  *       derived from this software without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
00022  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00023  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00024  * DISCLAIMED. IN NO EVENT SHALL ThE AUTHORS BE LIABLE FOR ANY
00025  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00026  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00028  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00029  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  ***************************************************************************/
00032 
00033 #ifndef PADDER_HPP_
00034 #define PADDER_HPP_
00035 
00036 using namespace std;
00037 
00038 namespace ebl {
00039 
00041   // padder
00042 
00043   template <typename T>
00044   padder<T>::padder(const idxdim &kerdims, bool mirror_)
00045     : nrow((int) (floor(kerdims.dim(0) / (float) 2.0))),
00046       ncol((int) (floor(kerdims.dim(1) / (float) 2.0))),
00047       nrow2(nrow), ncol2(ncol), bmirror(mirror_) {
00048     // remove 1 pixel on right and bottom borders if even.
00049     if (kerdims.dim(0) % 2 == 0)
00050       nrow2 -= 1;
00051     if (kerdims.dim(1) % 2 == 0)
00052       ncol2 -= 1;
00053   }
00054 
00055   template <typename T>
00056   padder<T>::~padder() {
00057   }
00058 
00059   template <typename T>
00060   idx<T> padder<T>::pad(idx<T> &in) {
00061     // allocate padded buffer
00062     idxdim d = in;
00063     d.setdim(1, d.dim(1) + nrow + nrow2);
00064     d.setdim(2, d.dim(2) + ncol + ncol2);
00065     idx<T> out(d);
00066     idx_clear(out);
00067     // copy in to padded buffer
00068     idx<T> tmp = out.narrow(1, in.dim(1), nrow);
00069     tmp = tmp.narrow(2, in.dim(2), ncol);
00070     idx_copy(in, tmp);
00071     if (bmirror)
00072       mirror(in, out);
00073     // return result
00074     return out;
00075   }
00076   
00077   template <typename T>
00078   void padder<T>::pad(idx<T> &in, idx<T> &out) {
00079     // allocate padded buffer
00080     idxdim d = in;
00081     d.setdim(1, d.dim(1) + nrow + nrow2);
00082     d.setdim(2, d.dim(2) + ncol + ncol2);
00083     if (out.get_idxdim() != d)
00084       out.resize(d);
00085     idx_clear(out);
00086     // copy in to padded buffer
00087     idx<T> tmp = out.narrow(1, in.dim(1), nrow);
00088     tmp = tmp.narrow(2, in.dim(2), ncol);
00089     idx_copy(in, tmp);
00090     if (bmirror)
00091       mirror(in, out);
00092   }
00093   
00094   template <typename T>
00095   void padder<T>::mirror(idx<T> &in, idx<T> &padded) {
00096     idx<T> tmp, tmp2;
00097     int i;
00098     // mirror border left
00099     for (i = std::max(0, (int) (ncol - in.dim(1) / 2)); i < ncol; ++i) {
00100       tmp2 = in.narrow(1, 1, ncol - i - 1);
00101       tmp = padded.narrow(1, 1, i);
00102       tmp = tmp.narrow(2, in.dim(2), ncol);
00103       idx_copy(tmp2, tmp);
00104     }
00105     // mirror border right
00106     for (i = std::max(0, (int) (ncol - in.dim(1) / 2)); i < ncol; ++i) {
00107       tmp2 = in.narrow(1, 1, in.dim(1) - ncol - 1 + i);
00108       tmp = padded.narrow(1, 1, padded.dim(1) - 1 - i);
00109       tmp = tmp.narrow(2, in.dim(2), ncol);
00110       idx_copy(tmp2, tmp);
00111     }
00112     // mirror border top using out as input
00113     for (i = std::max(0, (int) (nrow - in.dim(2) / 2)); i < nrow; ++i) {
00114       tmp2 = padded.narrow(2, 1, nrow + nrow - i - 1);
00115       tmp = padded.narrow(2, 1, i);
00116       idx_copy(tmp2, tmp);
00117     }
00118     // mirror border bottom using out as input
00119     for (i = std::max(0, (int) (nrow - in.dim(2) / 2)); i < nrow; ++i) {
00120       tmp2 = padded.narrow(2, 1, padded.dim(2) - nrow * 2 - 1 + i);
00121       tmp = padded.narrow(2, 1, padded.dim(2) - 1 - i);
00122       idx_copy(tmp2, tmp);
00123     }    
00124   }
00125 
00127   // padding utilities
00128   
00129   template <typename T> 
00130   idx<T> image_region_to_rect(idx<T> &im, const rect<int> &r, uint oheight,
00131                               uint owidth, rect<int> *cropped,
00132                               uint dh, uint dw) {
00133     // TODO: check that rectangle is within image
00134     if (im.order() != 2 && im.order() != 3)
00135       eblerror("expected a 2d or 3d input but got " << im);
00136     idxdim d(im);
00137     d.setdim(dh, oheight);
00138     d.setdim(dw, owidth);
00139     idx<T> res(d);
00140 
00141     float hcenter = r.h0 + (float) r.height / 2; // input height center
00142     float wcenter = r.w0 + (float) r.width / 2; // input width center
00143     // // limit centers to half the width/height away from borders
00144     // // to handle incorrect regions
00145     // hcenter = MIN((float)im.dim(dh) - (float)r.height/2,
00146     //            std::max((float)r.height/2, hcenter));
00147     // wcenter = MIN((float)im.dim(dw) - (float)r.width/2,
00148     //            std::max((float)r.width/2, wcenter));
00149     float h0 = hcenter - (float) oheight / 2; // out height offset in input
00150     float w0 = wcenter - (float) owidth / 2; // out width offset in input
00151     float h1 = hcenter + (float) oheight / 2;
00152     float w1 = wcenter + (float) owidth / 2;
00153     int gh0 = (int) std::max(0, (int) MIN(im.dim(dh), h0)); // input h offset
00154     int gw0 = (int) std::max(0, (int) MIN(im.dim(dw), w0)); // input w offset
00155     int gh1 = (int) std::max(0, (int) MIN(im.dim(dh), h1));
00156     int gw1 = (int) std::max(0, (int) MIN(im.dim(dw), w1));
00157     int h = gh1 - gh0 + std::max(0, -r.h0); // out height narrow
00158     int w = gw1 - gw0 + std::max(0, -r.w0); // out width narrow
00159     int fh0 = (int) std::max(0, (int) (gh0 - h0)); // out height offset narrow
00160     int fw0 = (int) std::max(0, (int) (gw0 - w0)); // out width offset narrow
00161 
00162     // narrow original image
00163     int hmin = std::max(0, std::min((int)res.dim(dh) - fh0,
00164                                     std::min((int)im.dim(dh) - gh0, h)));
00165     int wmin = std::max(0, std::min((int)res.dim(dw) - fw0,
00166                                     std::min((int)im.dim(dw) - gw0, w)));
00167     // clear result image
00168     idx_clear(res);
00169     if (hmin != 0 && wmin != 0) {// only copy if overlap with image      
00170       idx<T> tmpim = im.narrow(dh, hmin, gh0);
00171       tmpim = tmpim.narrow(dw, wmin, gw0);
00172       // narrow target image
00173       idx<T> tmpres = res.narrow(dh, hmin, fh0);
00174       tmpres = tmpres.narrow(dw, wmin, fw0);
00175       // copy original to target
00176       idx_copy(tmpim, tmpres);
00177     }
00178     // set cropped rectangle to region in the output image containing input
00179     if (cropped) {
00180       cropped->h0 = fh0;
00181       cropped->w0 = fw0;
00182       cropped->height = hmin;
00183       cropped->width = wmin;
00184     }
00185     return res;
00186   }
00187   
00188   template <typename T>
00189   void image_paste_center(idx<T> &in, idx<T> &out) {
00190     if (in.order() != 3 || out.order() != 3)
00191       eblerror("expected 3d idx but got " << in << " and " << out);
00192     int d0 = 1;
00193     int d1 = d0 + 1;
00194     intg ci = in.dim(d0) - out.dim(d0);
00195     intg cj = in.dim(d1) - out.dim(d1);
00196     intg xci = (int) (ci / 2);
00197     intg xcj = (int) (cj / 2);
00198     idx<T> i = in.narrow(d0, out.dim(d0), xci);
00199     i = i.narrow(d1, out.dim(d1), xcj);
00200     idx_copy(i, out);
00201   }
00202   
00203 } // end namespace ebl
00204 
00205 #endif /* PADDER_HPP_ */