examples/colorFilter/colorFilter.cpp

00001 /*
00002  *      Copyright (C) 2007, 2008. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00038 #include <QVApplication>
00039 #include <QVMPlayerCamera>
00040 #include <QVDefaultGUI>
00041 #include <QVImageCanvas>
00042 
00043 #include <math.h>
00044 #ifndef DOXYGEN_IGNORE_THIS
00045 
00046 void    colorFilter(const QVImage<sFloat,3> &image, QVImage<sFloat,3> &color, QVImage<sFloat,1> &light)
00047         {
00048         const uInt cols = image.getCols(), rows = image.getRows();
00049 
00050         Set((sFloat[3]){ 0.0, 0.0, 0.0 }, color);
00051         Set(0, light);
00052 
00053         QVIMAGE_INIT_READ(sFloat,image);
00054         QVIMAGE_INIT_WRITE(sFloat,color);
00055         QVIMAGE_INIT_WRITE(sFloat,light);
00056 
00057         for (int i = 0; i < cols; i++)
00058                 for (int j = 0; j < rows; j++)
00059                         {
00060                         const sDouble   r = QVIMAGE_PIXEL(image, i, j, 0),
00061                                         g = QVIMAGE_PIXEL(image, i, j, 1),
00062                                         b = QVIMAGE_PIXEL(image, i, j, 2),
00063                                         l = (r + g + b)/3;
00064                                         //l = 0.3*r + 0.59*g + 0.11*b;
00065                                         //l = pow(r*g*b, 0.1/0.3);
00066                         
00067                         QVIMAGE_PIXEL(color, i, j, 0) = 128.0*r/l;
00068                         QVIMAGE_PIXEL(color, i, j, 1) = 128.0*g/l;
00069                         QVIMAGE_PIXEL(color, i, j, 2) = 128.0*b/l;
00070 
00071                         QVIMAGE_PIXEL(light, i, j, 2) = l;
00072                         }
00073         }
00074 
00075 void restoreImageFromColorFilter(const QVImage<sFloat,3> &color, const QVImage<sFloat, 1> &light, QVImage<sFloat,3> &restored)
00076         {
00077         const uInt cols = color.getCols(), rows = color.getRows();
00078 
00079         QVIMAGE_INIT_READ(sFloat,color);
00080         QVIMAGE_INIT_READ(sFloat,light);
00081         QVIMAGE_INIT_WRITE(sFloat,restored);
00082 
00083         for (int i = 0; i < cols; i++)
00084                 for (int j = 0; j < rows; j++)
00085                         {
00086                         const sDouble   Cr = QVIMAGE_PIXEL(color, i, j, 0),
00087                                         Cg = QVIMAGE_PIXEL(color, i, j, 1),
00088                                         Cb = QVIMAGE_PIXEL(color, i, j, 2),
00089                                         l = QVIMAGE_PIXEL(light, i, j, 0);
00090 
00091                         QVIMAGE_PIXEL(restored, i, j, 0) = l*Cr/128.0;
00092                         QVIMAGE_PIXEL(restored, i, j, 1) = l*Cg/128.0;
00093                         QVIMAGE_PIXEL(restored, i, j, 2) = l*Cb/128.0;
00094                         }
00095 
00096         }
00097 
00098 void thresholdColors(QVImage<sFloat, 3> &color, const double threshold)
00099         {       
00100         const uInt cols = color.getCols(), rows = color.getRows();
00101 
00102         // Prune low colors
00103         // This sets all gray, white or dark colors to zero.
00104         QVIMAGE_INIT_WRITE(sFloat,color);
00105         for (int i = 0; i < cols; i++)
00106                 for (int j = 0; j < rows; j++)
00107                         {
00108                         const sFloat    Cr = QVIMAGE_PIXEL(color, i, j, 0),
00109                                         Cg = QVIMAGE_PIXEL(color, i, j, 1),
00110                                         Cb = QVIMAGE_PIXEL(color, i, j, 2),
00111                                         Cm = (Cr + Cg + Cb)/3.0;
00112 
00113                         if ( ABS(Cr-Cm)+ABS(Cg-Cm)+ABS(Cb-Cm) < threshold*3.0)
00114                                 {
00115                                 QVIMAGE_PIXEL(color, i, j, 0) = 0.0;
00116                                 QVIMAGE_PIXEL(color, i, j, 1) = 0.0;
00117                                 QVIMAGE_PIXEL(color, i, j, 2) = 0.0;
00118                                 }
00119                         }
00120 
00121         // Threshold colors
00122         // This lowers the resolution of the colors, to diferenciate better different colors.
00123         for (int i = 0; i < cols; i++)
00124                 for (int j = 0; j < rows; j++)
00125                         {
00126                         sFloat  Cr = QVIMAGE_PIXEL(color, i, j, 0),
00127                                 Cg = QVIMAGE_PIXEL(color, i, j, 1),
00128                                 Cb = QVIMAGE_PIXEL(color, i, j, 2);
00129 
00130                         if      (Cr > 240.0)    Cr = 255.0;
00131                         else if (Cr > 208.0)    Cr = 224.0;
00132                         else if (Cr > 176.0)    Cr = 192.0;
00133                         else if (Cr > 144.0)    Cr = 160.0;
00134                         else if (Cr > 112.0)    Cr = 128.0;
00135                         else if (Cr > 80.0)     Cr = 96.0;
00136                         else if (Cr > 48.0)     Cr = 64.0;
00137                         else if (Cr > 16.0)     Cr = 32.0;
00138                         else                    Cr = 0.0;
00139 
00140                         if      (Cg > 240.0)    Cg = 255.0;
00141                         else if (Cg > 208.0)    Cg = 224.0;
00142                         else if (Cg > 176.0)    Cg = 192.0;
00143                         else if (Cg > 144.0)    Cg = 160.0;
00144                         else if (Cg > 112.0)    Cg = 128.0;
00145                         else if (Cg > 80.0)     Cg = 96.0;
00146                         else if (Cg > 48.0)     Cg = 64.0;
00147                         else if (Cg > 16.0)     Cg = 32.0;
00148                         else                    Cg = 0.0;
00149 
00150                         if      (Cb > 240.0)    Cb = 255.0;
00151                         else if (Cb > 208.0)    Cb = 224.0;
00152                         else if (Cb > 176.0)    Cb = 192.0;
00153                         else if (Cb > 144.0)    Cb = 160.0;
00154                         else if (Cb > 112.0)    Cb = 128.0;
00155                         else if (Cb > 80.0)     Cb = 96.0;
00156                         else if (Cb > 48.0)     Cb = 64.0;
00157                         else if (Cb > 16.0)     Cb = 32.0;
00158                         else                    Cb = 0.0;
00159 
00160                         QVIMAGE_PIXEL(color, i, j, 0) = Cr;
00161                         QVIMAGE_PIXEL(color, i, j, 1) = Cg;
00162                         QVIMAGE_PIXEL(color, i, j, 2) = Cb;
00163                         }
00164         }
00165 
00166 class PlayerWorker: public QVWorker
00167         {
00168         public:
00169                 PlayerWorker(QString name): QVWorker(name)
00170                         {
00171                         addProperty< QVImage<uChar,3> >("Input image", inputFlag|outputFlag);
00172 
00173                         addProperty< QVImage<uChar,3> >("Color image", outputFlag);
00174                         addProperty< QVImage<uChar,1> >("Light image", outputFlag);
00175                         addProperty< QVImage<uChar,3> >("Restored image", outputFlag);
00176                         addProperty<double>("Threshold", inputFlag, 10.0, "", 0.0, 64.0);
00177                         }
00178 
00179                 void iterate()
00180                         {
00181                         const QVImage<sFloat,3> inputImage = getPropertyValue< QVImage<uChar,3> >("Input image");
00182                         const uInt cols = inputImage.getCols(), rows = inputImage.getRows();
00183                         //QVImage<uChar,3> inputImage(cols, rows);
00184                         //YUV420ToRGB(imageY, imageU, imageV, inputImage);
00185                         
00186                         QVImage<sFloat,3> imageTemp = inputImage, image = imageTemp;
00187 
00188                         const double threshold = getPropertyValue< double >("Threshold");
00189 
00190                         FilterGauss(imageTemp, image);
00191 
00192                         QVImage<sFloat,3> color(cols, rows);
00193                         QVImage<sFloat,1> light(cols, rows);
00194 
00195                         // Separate luminance and color
00196                         colorFilter(image, color, light);
00197 
00198                         thresholdColors(color, threshold);
00199 
00200                         // Restore image
00201                         QVImage<sFloat,3> restored(cols, rows);
00202 
00203                         restoreImageFromColorFilter(color, light, restored);
00204 
00205                         setPropertyValue< QVImage<uChar,3> >("Input image", inputImage);
00206                         setPropertyValue< QVImage<uChar,3> >("Color image", color);
00207                         setPropertyValue< QVImage<uChar,1> >("Light image", light);
00208                         setPropertyValue< QVImage<uChar,3> >("Restored image", restored);
00209                         }
00210         };
00211 
00212 int main(int argc, char *argv[])
00213         {
00214         QVApplication app(argc, argv,
00215                 "Example program for QVision library. Displays the contents of a video source."
00216                 );
00217 
00218         QVMPlayerCamera camera("Video");
00219         PlayerWorker worker("Video player worker");
00220         camera.link(&worker,"Input image");
00221 
00222         QVDefaultGUI interface;
00223 
00224         QVImageCanvas imageCanvas1("Original image");
00225         imageCanvas1.linkProperty(worker, "Input image");
00226 
00227         QVImageCanvas imageCanvas2("Color image");
00228         imageCanvas2.linkProperty(worker, "Color image");
00229 
00230         QVImageCanvas imageCanvas3("Light image");
00231         imageCanvas3.linkProperty(worker, "Light image");
00232 
00233         QVImageCanvas imageCanvas4("Restored image");
00234         imageCanvas4.linkProperty(worker, "Restored image");
00235 
00236         return app.exec();
00237         }
00238 
00239 #endif