libidx
|
00001 /*************************************************************************** 00002 * Copyright (C) 2009 by Pierre Sermanet * 00003 * pierre.sermanet@gmail.com * 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * * Redistributions of source code must retain the above copyright 00008 * notice, this list of conditions and the following disclaimer. 00009 * * Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * * Redistribution under a license not approved by the Open Source 00013 * Initiative (http://www.opensource.org) must display the 00014 * following acknowledgement in all advertising material: 00015 * This product includes software developed at the Courant 00016 * Institute of Mathematical Sciences (http://cims.nyu.edu). 00017 * * The names of the authors may not be used to endorse or promote products 00018 * derived from this software without specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 00021 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00023 * DISCLAIMED. IN NO EVENT SHALL ThE AUTHORS BE LIABLE FOR ANY 00024 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00027 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 ***************************************************************************/ 00031 00032 #ifndef COLOR_SPACES_HPP_ 00033 #define COLOR_SPACES_HPP_ 00034 00035 #include <math.h> 00036 00037 using namespace std; 00038 00039 namespace ebl { 00040 00042 // RGB -> YUV 00043 00044 // TODO: find a cleaner way with matrix multiplication that can handle 00045 // different output type than yuv matrix. 00046 template<class T> void rgb_to_yuv_1D(idx<T> &rgb, idx<T> &yuv) { 00047 if (rgb.idx_ptr() == yuv.idx_ptr()) { 00048 eblerror("rgb_to_yuv: dst must be different than src"); 00049 return ; 00050 } 00051 double r, g, b; 00052 r = rgb.get(0); 00053 g = rgb.get(1); 00054 b = rgb.get(2); 00055 yuv.set((T) ( 0.299 * r + 0.587 * g + 0.114 * b), 0); 00056 yuv.set((T) ((-0.147 * r - 0.289 * g + 0.437 * b + 111) * 1.14678), 1); 00057 yuv.set((T) (( 0.615 * r - 0.515 * g - 0.100 * b + 157) * 0.81300), 2); 00058 } 00059 00060 template<class T> void rgb_to_yuv(idx<T> &rgb, idx<T> &yuv) { 00061 idx_checknelems2_all(rgb, yuv); 00062 switch (rgb.order()) { 00063 case 1: // process 1 pixel 00064 rgb_to_yuv_1D(rgb, yuv); 00065 // idx_m2dotm1(rgb_yuv, rgb, yuv); 00066 return ; 00067 case 3: // process 2D image 00068 { idx_bloop2(rg, rgb, T, yu, yuv, T) { 00069 { idx_bloop2(r, rg, T, y, yu, T) { 00070 rgb_to_yuv_1D(r, y); 00071 // idx_m2dotm1(rgb_yuv, r, y); 00072 }} 00073 }} 00074 return ; 00075 default: 00076 eblerror("rgb_to_yuv dimension not implemented"); 00077 } 00078 } 00079 00080 // TODO: find a cleaner way with matrix multiplication that can handle 00081 // different output type than y matrix. 00082 template<class T> void rgb_to_y_1D(idx<T> &rgb, idx<T> &y) { 00083 if (rgb.idx_ptr() == y.idx_ptr()) { 00084 eblerror("rgb_to_y: dst must be different than src"); 00085 return ; 00086 } 00087 double r, g, b; 00088 r = rgb.get(0); 00089 g = rgb.get(1); 00090 b = rgb.get(2); 00091 y.set( (T) 0.299 * (T) r + (T) 0.587 * (T) g + (T) 0.114 * (T) b, 0); 00092 } 00093 00094 template<class T> void rgb_to_y(idx<T> &rgb, idx<T> &y) { 00095 switch (rgb.order()) { 00096 case 1: // process 1 pixel 00097 rgb_to_y_1D(rgb, y); 00098 // idx_m2dotm1(rgb_yuv, rgb, yuv); 00099 return ; 00100 case 3: // process 2D image 00101 { idx_bloop2(rg, rgb, T, yy, y, T) { 00102 { idx_bloop2(r, rg, T, yyy, yy, T) { 00103 rgb_to_y_1D(r, yyy); 00104 // idx_m2dotm1(rgb_yuv, r, y); 00105 }} 00106 }} 00107 return ; 00108 default: 00109 eblerror("rgb_to_y dimension not implemented"); 00110 } 00111 } 00112 00113 template<class T> idx<T> rgb_to_yuv(idx<T> &rgb) { 00114 idxdim d(rgb); 00115 idx<T> yuv(d); 00116 rgb_to_yuv(rgb, yuv); 00117 return yuv; 00118 } 00119 00121 // BGR -> YUV 00122 00123 // TODO: find a cleaner way with matrix multiplication that can handle 00124 // different output type than yuv matrix. 00125 template<class T> void bgr_to_yuv_1D(idx<T> &bgr, idx<T> &yuv) { 00126 if (bgr.idx_ptr() == yuv.idx_ptr()) { 00127 eblerror("bgr_to_yuv: dst must be different than src"); 00128 return ; 00129 } 00130 double r, g, b; 00131 b = bgr.get(0); 00132 g = bgr.get(1); 00133 r = bgr.get(2); 00134 yuv.set( 0.299 * r + 0.587 * g + 0.114 * b, 0); 00135 yuv.set((-0.147 * r - 0.289 * g + 0.437 * b + 111) * 1.14678, 1); 00136 yuv.set(( 0.615 * r - 0.515 * g - 0.100 * b + 157) * 0.81300, 2); 00137 } 00138 00139 // TODO: find a cleaner way with matrix multiplication that can handle 00140 // different output type than y matrix. 00141 template<class T> void bgr_to_y_1D(idx<T> &bgr, idx<T> &y) { 00142 if (bgr.idx_ptr() == y.idx_ptr()) { 00143 eblerror("bgr_to_y: dst must be different than src"); 00144 return ; 00145 } 00146 double r, g, b; 00147 b = bgr.get(0); 00148 g = bgr.get(1); 00149 r = bgr.get(2); 00150 y.set( 0.299 * r + 0.587 * g + 0.114 * b, 0); 00151 } 00152 00153 template<class T> void bgr_to_y(idx<T> &bgr, idx<T> &y) { 00154 switch (bgr.order()) { 00155 case 1: // process 1 pixel 00156 bgr_to_y_1D(bgr, y); 00157 return ; 00158 case 3: // process 2D image 00159 { idx_bloop2(bg, bgr, T, yy, y, T) { 00160 { idx_bloop2(b, bg, T, yyy, yy, T) { 00161 rgb_to_y_1D(b, yyy); 00162 }} 00163 }} 00164 return ; 00165 default: 00166 eblerror("bgr_to_y dimension not implemented"); 00167 } 00168 } 00169 00171 // YUV -> RGB 00172 00173 template<class T> void yuv_to_rgb_1D(idx<T> &yuv, idx<T> &rgb) { 00174 if (rgb.idx_ptr() == yuv.idx_ptr()) { 00175 eblerror("yuv_to_rgb: dst must be different than src"); 00176 return ; 00177 } 00178 float y, u, v; 00179 y = std::min((float) 255, std::max((float) 0, 00180 (float) ((float) 1.164383562 00181 * (yuv.get(0) - 16)))); 00182 u = std::min((float) 128, std::max((float) -127, 00183 (float) ((float) 1.133928571 00184 * (yuv.get(1) - 128)))); 00185 v = std::min((float) 128, std::max((float) -127, 00186 (float) ((float) 1.133928571 00187 * (yuv.get(2) - 128)))); 00188 rgb.set(std::min((T) 255, std::max((T) 0, 00189 (T) (1.0 * y + 0.00000 * u + 1.402 * v))), 0); 00190 rgb.set(std::min((T) 255, std::max((T) 0, 00191 (T) (1.0 * y - 0.344 * u - 0.714 * v))), 1); 00192 rgb.set(std::min((T) 255, std::max((T) 0, 00193 (T) (1.0 * y + 1.772 * u + 0.00000 * v))), 2); 00194 } 00195 00196 template<class T> void yuv_to_rgb(idx<T> &yuv, idx<T> &rgb) { 00197 idx_checknelems2_all(rgb, yuv); 00198 switch (yuv.order()) { 00199 case 1: // process 1 pixel 00200 yuv_to_rgb_1D(yuv, rgb); 00201 //idx_m2dotm1(yuv_rgb, yuv, rgb); 00202 return ; 00203 case 3: // process 2D image 00204 { idx_bloop2(rg, rgb, T, yu, yuv, T) { 00205 { idx_bloop2(r, rg, T, y, yu, T) { 00206 yuv_to_rgb_1D(y, r); 00207 //idx_m2dotm1(yuv_rgb, y, r); 00208 }} 00209 }} 00210 return ; 00211 default: 00212 eblerror("yuv_to_rgb dimension not implemented"); 00213 } 00214 } 00215 00216 template<class T> idx<T> yuv_to_rgb(idx<T> &yuv) { 00217 idxdim d(yuv); 00218 idx<T> rgb(d); 00219 yuv_to_rgb(yuv, rgb); 00220 return rgb; 00221 } 00222 00224 // HSV 00225 00226 // TODO: find a cleaner way with matrix multiplication that can handle 00227 // different output type than hsv matrix. 00228 template<class T> void rgb_to_hsv_1D(idx<T> &rgb, idx<T> &hsv) { 00229 if (rgb.idx_ptr() == hsv.idx_ptr()) { 00230 eblerror("rgb_to_hsv: dst must be different than src"); 00231 return ; 00232 } 00233 double r, g, b; 00234 r = rgb.get(0); 00235 g = rgb.get(1); 00236 b = rgb.get(2); 00237 double h, s, v; 00238 PIX_RGB_TO_HSV_COMMON(r, g, b, h, s, v, false); 00239 hsv.set((T) h, 0); 00240 hsv.set((T) s, 1); 00241 hsv.set((T) v, 2); 00242 } 00243 00244 template<class T> void rgb_to_h_1D(idx<T> &rgb, idx<T> &h) { 00245 if (rgb.idx_ptr() == h.idx_ptr()) { 00246 eblerror("rgb_to_h: dst must be different than src"); 00247 return ; 00248 } 00249 double r, g, b; 00250 r = rgb.get(0); 00251 g = rgb.get(1); 00252 b = rgb.get(2); 00253 double h_, s_, v_; 00254 PIX_RGB_TO_HSV_COMMON(r, g, b, h_, s_, v_, false); 00255 h.set((T) h_, 0); 00256 } 00257 00258 template<class T> void rgb_to_hsv(idx<T> &rgb, idx<T> &hsv) { 00259 idx_checknelems2_all(rgb, hsv); 00260 switch (rgb.order()) { 00261 case 1: // process 1 pixel 00262 rgb_to_hsv_1D(rgb, hsv); 00263 // idx_m2dotm1(rgb_hsv, rgb, hsv); 00264 return ; 00265 case 3: // process 2D image 00266 { idx_bloop2(rg, rgb, T, yu, hsv, T) { 00267 { idx_bloop2(r, rg, T, y, yu, T) { 00268 rgb_to_hsv_1D(r, y); 00269 // idx_m2dotm1(rgb_hsv, r, y); 00270 }} 00271 }} 00272 return ; 00273 default: 00274 eblerror("rgb_to_hsv dimension not implemented"); 00275 } 00276 } 00277 00278 template<class T> idx<T> rgb_to_hsv(idx<T> &rgb) { 00279 idxdim d(rgb); 00280 idx<T> hsv(d); 00281 rgb_to_hsv(rgb, hsv); 00282 return hsv; 00283 } 00284 00285 template<class T> void hsv_to_rgb_1D(idx<T> &hsv, idx<T> &rgb) { 00286 if (rgb.idx_ptr() == hsv.idx_ptr()) { 00287 eblerror("hsv_to_rgb: dst must be different than src"); 00288 return ; 00289 } 00290 double h, s, v; 00291 h = hsv.get(0); 00292 s = hsv.get(1); 00293 v = hsv.get(2); 00294 double r, g, b; 00295 PIX_HSV_TO_RGB_COMMON(h, s, v, r, g, b); 00296 rgb.set((T)r, 0); 00297 rgb.set((T)g, 1); 00298 rgb.set((T)b, 2); 00299 } 00300 00301 template<class T> void hsv_to_rgb(idx<T> &hsv, idx<T> &rgb) { 00302 idx_checknelems2_all(rgb, hsv); 00303 switch (hsv.order()) { 00304 case 1: // process 1 pixel 00305 hsv_to_rgb_1D(hsv, rgb); 00306 //idx_m2dotm1(hsv_rgb, hsv, rgb); 00307 return ; 00308 case 3: // process 2D image 00309 { idx_bloop2(rg, rgb, T, yu, hsv, T) { 00310 { idx_bloop2(r, rg, T, y, yu, T) { 00311 hsv_to_rgb_1D(y, r); 00312 //idx_m2dotm1(hsv_rgb, y, r); 00313 }} 00314 }} 00315 return ; 00316 default: 00317 eblerror("hsv_to_rgb dimension not implemented"); 00318 } 00319 } 00320 00321 template<class T> idx<T> hsv_to_rgb(idx<T> &hsv) { 00322 idxdim d(hsv); 00323 idx<T> rgb(d); 00324 hsv_to_rgb(hsv, rgb); 00325 return rgb; 00326 } 00327 00329 // HSV3 00330 00331 // TODO: find a cleaner way with matrix multiplication that can handle 00332 // different output type than hsv3 matrix. 00333 template<class T> void rgb_to_hsv3_1D(idx<T> &rgb, idx<T> &hsv3, 00334 double threshold1, double threshold2) { 00335 if (rgb.idx_ptr() == hsv3.idx_ptr()) { 00336 eblerror("rgb_to_hsv3: dst must be different than src"); 00337 return ; 00338 } 00339 double r, g, b; 00340 r = rgb.get(0); 00341 g = rgb.get(1); 00342 b = rgb.get(2); 00343 double h, s, v; 00344 PIX_RGB_TO_HSV_COMMON(r, g, b, h, s, v, false); 00345 if ((s < threshold1) || (v < threshold2)) { 00346 h = 360 + 60 * v; 00347 } 00348 hsv3.set((T) h, 0); 00349 hsv3.set((T) s, 1); 00350 hsv3.set((T) v, 2); 00351 } 00352 00353 template<class T> void rgb_to_hsv3(idx<T> &rgb, idx<T> &hsv3, 00354 double threshold1, double threshold2) { 00355 idx_checknelems2_all(rgb, hsv3); 00356 switch (rgb.order()) { 00357 case 1: // process 1 pixel 00358 rgb_to_hsv3_1D(rgb, hsv3, threshold1, threshold2); 00359 // idx_m2dotm1(rgb_hsv3, rgb, hsv3); 00360 return ; 00361 case 3: // process 2D image 00362 { idx_bloop2(rg, rgb, T, yu, hsv3, T) { 00363 { idx_bloop2(r, rg, T, y, yu, T) { 00364 rgb_to_hsv3_1D(r, y, threshold1, threshold2); 00365 // idx_m2dotm1(rgb_hsv3, r, y); 00366 }} 00367 }} 00368 return ; 00369 default: 00370 eblerror("rgb_to_hsv3 dimension not implemented"); 00371 } 00372 } 00373 00374 template<class T> idx<T> rgb_to_hsv3(idx<T> &rgb, double threshold1, 00375 double threshold2) { 00376 idxdim d(rgb); 00377 idx<T> hsv3(d); 00378 rgb_to_hsv3(rgb, hsv3, threshold1, threshold2); 00379 return hsv3; 00380 } 00381 00382 template<class T> void hsv3_to_rgb_1D(idx<T> &hsv3, idx<T> &rgb) { 00383 if (rgb.idx_ptr() == hsv3.idx_ptr()) { 00384 eblerror("hsv3_to_rgb: dst must be different than src"); 00385 return ; 00386 } 00387 double h, s, v; 00388 h = hsv3.get(0); 00389 s = hsv3.get(1); 00390 v = hsv3.get(2); 00391 double r, g, b; 00392 PIX_HSV3_TO_RGB_COMMON(h, s, v, r, g, b); 00393 rgb.set((T)r, 0); 00394 rgb.set((T)g, 1); 00395 rgb.set((T)b, 2); 00396 } 00397 00398 template<class T> void hsv3_to_rgb(idx<T> &hsv3, idx<T> &rgb) { 00399 idx_checknelems2_all(rgb, hsv3); 00400 switch (hsv3.order()) { 00401 case 1: // process 1 pixel 00402 hsv3_to_rgb_1D(hsv3, rgb); 00403 //idx_m2dotm1(hsv3_rgb, hsv3, rgb); 00404 return ; 00405 case 3: // process 2D image 00406 { idx_bloop2(rg, rgb, T, yu, hsv3, T) { 00407 { idx_bloop2(r, rg, T, y, yu, T) { 00408 hsv3_to_rgb_1D(y, r); 00409 //idx_m2dotm1(hsv3_rgb, y, r); 00410 }} 00411 }} 00412 return ; 00413 default: 00414 eblerror("hsv3_to_rgb dimension not implemented"); 00415 } 00416 } 00417 00418 template<class T> idx<T> hsv3_to_rgb(idx<T> &hsv3) { 00419 idxdim d(hsv3); 00420 idx<T> rgb(d); 00421 hsv3_to_rgb(hsv3, rgb); 00422 return rgb; 00423 } 00424 00426 // YH3 00427 00428 // TODO: find a cleaner way with matrix multiplication that can handle 00429 // different output type than yh3 matrix. 00430 template<class T> void rgb_to_yh3_1D(idx<T> &rgb, idx<T> &yh3, 00431 double threshold1, double threshold2) { 00432 if (rgb.idx_ptr() == yh3.idx_ptr()) { 00433 eblerror("rgb_to_yh3: dst must be different than src"); 00434 return ; 00435 } 00436 idx<T> hsv3(3); 00437 rgb_to_hsv3_1D(rgb, hsv3, threshold1, threshold2); 00438 yh3.set((0.299 * rgb.get(0) + 0.587 * rgb.get(1) + 0.114 * rgb.get(2)) 00439 /255.0, 0); 00440 yh3.set(hsv3.get(0) / 210.0 - 1, 1); 00441 } 00442 00443 template<class T> void rgb_to_yh3(idx<T> &rgb, idx<T> &yh3, 00444 double threshold1, double threshold2) { 00445 // idx_checknelems2_all(rgb, yh3); 00446 switch (rgb.order()) { 00447 case 1: // process 1 pixel 00448 rgb_to_yh3_1D(rgb, yh3, threshold1, threshold2); 00449 // idx_m2dotm1(rgb_yh3, rgb, yh3); 00450 return ; 00451 case 3: // process 2D image 00452 { idx_bloop2(rg, rgb, T, yu, yh3, T) { 00453 { idx_bloop2(r, rg, T, y, yu, T) { 00454 rgb_to_yh3_1D(r, y, threshold1, threshold2); 00455 // idx_m2dotm1(rgb_yh3, r, y); 00456 }} 00457 }} 00458 return ; 00459 default: 00460 eblerror("rgb_to_yh3 dimension not implemented"); 00461 } 00462 } 00463 00464 template<class T> idx<T> rgb_to_yh3(idx<T> &rgb, double threshold1, 00465 double threshold2) { 00466 idxdim d(rgb); 00467 idx<T> yh3(d); 00468 rgb_to_yh3(rgb, yh3, threshold1, threshold2); 00469 return yh3; 00470 } 00471 00472 template<class T> void h3_to_rgb_1D(idx<T> &h3, idx<T> &rgb) { 00473 if (rgb.idx_ptr() == h3.idx_ptr()) { 00474 eblerror("h3_to_rgb: dst must be different than src"); 00475 return ; 00476 } 00477 double r, g, b; 00478 PIX_HSV3_TO_RGB_COMMON(h3.get(), .5, .5, r, g, b); 00479 rgb.set((T)r, 0); 00480 rgb.set((T)g, 1); 00481 rgb.set((T)b, 2); 00482 } 00483 00484 template<class T> void h3_to_rgb(idx<T> &h3, idx<T> &rgb) { 00485 // idx_checknelems2_all(rgb, h3); 00486 switch (h3.order()) { 00487 case 2: // process 1 pixel 00488 // h3_to_rgb_1D(h3, rgb); 00489 // //idx_m2dotm1(h3_rgb, h3, rgb); 00490 // return ; 00491 case 3: // process 2D image 00492 { idx_bloop2(rg, rgb, T, yu, h3, T) { 00493 { idx_bloop2(r, rg, T, y, yu, T) { 00494 h3_to_rgb_1D(y, r); 00495 //idx_m2dotm1(h3_rgb, y, r); 00496 }} 00497 }} 00498 return ; 00499 default: 00500 eblerror("h3_to_rgb dimension not implemented"); 00501 } 00502 } 00503 00504 template<class T> idx<T> h3_to_rgb(idx<T> &h3) { 00505 idxdim d(h3); 00506 idx<T> rgb(d); 00507 h3_to_rgb(h3, rgb); 00508 return rgb; 00509 } 00510 00512 // H2sv 00513 00514 // TODO: find a cleaner way with matrix multiplication that can handle 00515 // different output type than h2sv matrix. 00516 template<class T> void rgb_to_h2sv_1D(idx<T> &rgb, idx<T> &h2sv) { 00517 if (rgb.idx_ptr() == h2sv.idx_ptr()) { 00518 eblerror("rgb_to_h2sv: dst must be different than src"); 00519 return ; 00520 } 00521 double r, g, b; 00522 r = rgb.get(0); 00523 g = rgb.get(1); 00524 b = rgb.get(2); 00525 double h, s, v, h1, h2; 00526 PIX_RGB_TO_HSV_COMMON(r, g, b, h, s, v, false); 00527 PIX_HSV_TO_H2SV1_COMMON(h, h1, h2); 00528 h2sv.set((T)h1, 0); 00529 h2sv.set((T)h2, 1); 00530 h2sv.set((T)s, 2); 00531 h2sv.set((T)v, 3); 00532 } 00533 00534 template<class T> void rgb_to_h2sv(idx<T> &rgb, idx<T> &h2sv) { 00535 // idx_checknelems2_all(rgb, h2sv); 00536 switch (rgb.order()) { 00537 case 1: // process 1 pixel 00538 rgb_to_h2sv_1D(rgb, h2sv); 00539 // idx_m2dotm1(rgb_h2sv, rgb, h2sv); 00540 return ; 00541 case 3: // process 2D image 00542 { idx_bloop2(rg, rgb, T, yu, h2sv, T) { 00543 { idx_bloop2(r, rg, T, y, yu, T) { 00544 rgb_to_h2sv_1D(r, y); 00545 // idx_m2dotm1(rgb_h2sv, r, y); 00546 }} 00547 }} 00548 return ; 00549 default: 00550 eblerror("rgb_to_h2sv dimension not implemented"); 00551 } 00552 } 00553 00555 // VpH2SV 00556 00557 template<class T> void rgb_to_vph2sv(idx<T> &rgb, idx<T> &vph2sv, 00558 double s, int n) { 00559 // TODO: check dimensions, dimension where channels are 00560 idx<T> h2sv = vph2sv.narrow(2, vph2sv.dim(2) - 1, 1); 00561 idx<T> vp = vph2sv.select(2, 0); 00562 idx<T> v = vph2sv.select(2, 4); 00563 idxdim d(vp); 00564 idx<T> tmp(d); 00565 rgb_to_h2sv(rgb, h2sv); 00566 idx_copy(v, tmp); 00567 // image_mexican_filter(tmp, vp, s, n); 00568 image_global_normalization(tmp); 00569 image_local_normalization(tmp, vp, n); 00570 // vph2sv = vph2sv.narrow(0, vph2sv.dim(0) - n + 1, floor(n / 2)); 00571 // vph2sv = vph2sv.narrow(1, vph2sv.dim(1) - n + 1, floor(n / 2)); 00572 } 00573 00574 } // end namespace ebl 00575 00576 #endif /* COLOR_SPACES_HPP_ */