libidx
|
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_ */