libidx
/home/rex/ebltrunk/core/libidx/include/color_spaces.hpp
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_ */