///////////////////////////////////////////////////////////////////////////// // Name: crvcolor.cpp // Purpose: // Author: Cesar Mauri Loba (cesar at crea-si dot com) // Modified by: // Created: // Copyright: (C) 2008 Cesar Mauri Loba - CREA Software Systems // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . ///////////////////////////////////////////////////////////////////////////// #include #include #include "crvcolor.h" #include "crvmisc.h" #include "crvgeomtry.h" void CRGBCubicColor::Clear() { memset (m_ColorLookup, 0, 256*256*256); } void CRGBCubicColor::TrainColor (unsigned char r, unsigned char g, unsigned char b, int radius, double dDivisor) { int rRadius, gRadius, bRadius, iR, iG, iB; t3DRPoint p1, p2; double val; if (r< radius) rRadius= r; else if ((255 - r)< radius) rRadius= (255 - r); else rRadius= radius; if (g< radius) gRadius= g; else if ((255 - g)< radius) gRadius= (255 - g); else gRadius= radius; if (b< radius) bRadius= b; else if ((255 - b)< radius) bRadius= (255 - b); else bRadius= radius; p1.x= r; p1.y= g; p1.z= b; for (iR= (int) r - rRadius; iR<= (int) r + rRadius; iR++) { for (iG= (int) g - gRadius; iG<= (int) g + gRadius; iG++) { for (iB= (int) b - bRadius; iB<= (int) b + bRadius; iB++) { p2.x= iR; p2.y= iG; p2.z= iB; val= 255.0 / (points3d_distance (&p1, &p2) / dDivisor + 1.0); val+= m_ColorLookup[iR][iG][iB]; if (val>= 255.0) m_ColorLookup[iR][iG][iB]= 255; else m_ColorLookup[iR][iG][iB]= (unsigned char) val; } } } } // Realitza entrenament per una imatge IPL tenint en compte ROI void CRGBCubicColor::TrainImage (const IplImage *img, int radius, double dDivisor) { int x, y, xIni, yIni, xLim, yLim; unsigned char *pImg; assert (img && img->imageData); assert (!strncmp (img->colorModel, "RGBA", 4) && !strncmp (img->channelSeq, "BGRA", 4)); // Límits on s'ha d'aplicar la funció crvGetROILimits (img, xIni, yIni, xLim, yLim); // Aplica tractament a la ROI for (y= yIni; y< yLim; y++) { // Apuntador inici fila component R pImg= (unsigned char *) crvImgOffset (img, xIni, y); for (x= xIni; x< xLim; x++) { TrainColor (pImg[2], pImg[1], pImg[0], radius, dDivisor); pImg+= 4; } } } // Genera imatge resultant d'indexar la taula // per tots els píxels // De moment només vàlid per imatges RGBA void CRGBCubicColor::LookupImage (const IplImage *pSrc, IplImage *pDst) { int x, y, xIni, yIni, xLim, yLim; unsigned char *pSrcB, *pDstB; assert (pSrc && pSrc->imageData && pDst && pDst->imageData); assert (!strncmp (pSrc->colorModel, "RGBA", 4) && !strncmp (pSrc->channelSeq, "BGRA", 4) && !strncmp (pDst->colorModel, "GRAY", 4) && !strncmp (pDst->channelSeq, "GRAY", 4) ); // Límits on s'ha d'aplicar la funció crvGetROILimits (pSrc, xIni, yIni, xLim, yLim); // Aplica tractament a la ROI for (y= yIni; y< yLim; y++) { // Apuntador inici fila component R pSrcB= (unsigned char *) crvImgOffset (pSrc, xIni, y); pDstB= (unsigned char *) crvImgOffset (pDst, xIni, y); for (x= xIni; x< xLim; x++) { *pDstB= m_ColorLookup[pSrcB[2]][pSrcB[1]][pSrcB[0]]; //pDstB[1]= pDstB[0]; //pDstB[2]= pDstB[0]; //pDstB[3]= pSrcB[3]; pSrcB+= 4; pDstB++; } } } // Genera constants model de color a partir de la ROI // d'una imatge RGBA void crvExtractSkinColorModel (IplImage *pIpl, float &krg_min, float &krg_max, float &krb_min, float &krb_max) { int x, y, xIni, yIni, xLim, yLim; float krg, krb; unsigned char *pSrc; assert (pIpl); // Inicialitzacions krg_min= 9999999999.0f; krb_min= 9999999999.0f; krg_max= -9999999999.0f; krb_max= -9999999999.0f; // Límits on s'ha d'aplicar la funció crvGetROILimits (pIpl, xIni, yIni, xLim, yLim); // Aplica tractament a la ROI for (y= yIni; y< yLim; y++) { // Apuntador inici fila component R pSrc= (unsigned char *) crvImgOffset (pIpl, xIni, y); for (x= xIni; x< xLim; x++) { krg= (float) pSrc[0] / (float) pSrc[1]; krb= (float) pSrc[0] / (float) pSrc[2]; pSrc+= 4; if (krg< krg_min) krg_min= krg; if (krg> krg_max) krg_max= krg; if (krb< krb_min) krb_min= krb; if (krb> krb_max) krb_max= krb; } } } // Converteix una imatge a color a escala de grisos void crvColorToGray (const IplImage *pImgSrc, IplImage *pImgDst) { int x, y, xIni, yIni, xLim, yLim; int xDstIni, yDstIni, xDstLim, yDstLim; unsigned char *pSrcPix, *pDstPix; unsigned int sum; assert (pImgSrc && pImgDst && pImgSrc!= pImgDst && pImgSrc->imageData!= pImgDst->imageData); assert (pImgSrc->depth== IPL_DEPTH_8U && pImgDst->depth== IPL_DEPTH_8U); assert (((!strncmp (pImgSrc->channelSeq, "BGRA", 4) && pImgSrc->nChannels== 4) || (!strncmp (pImgSrc->channelSeq, "BGR", 4) && pImgSrc->nChannels== 3) || (!strncmp (pImgSrc->channelSeq, "RGB", 4) && pImgSrc->nChannels== 3)) && !strncmp (pImgDst->channelSeq, "GRAY", 4) ); // PROV: les ROI han de ser indèntiques crvGetROILimits (pImgSrc, xIni, yIni, xLim, yLim); crvGetROILimits (pImgDst, xDstIni, yDstIni, xDstLim, yDstLim); assert (xIni== xDstIni && yIni== yDstIni && xLim== xDstLim && yLim== yDstLim); if (pImgSrc->nChannels== 3) { // 3 channels for (y= yIni; y< yLim; y++) { pSrcPix= (unsigned char *) crvImgOffset (pImgSrc, xIni, y); pDstPix= (unsigned char *) crvImgOffset (pImgDst, xIni, y); for (x= xIni; x< xLim; x++) { sum= *pSrcPix; pSrcPix++; // B sum+= *pSrcPix; pSrcPix++; // G sum+= *pSrcPix; pSrcPix++; // R *pDstPix= (unsigned char) (sum / 3); pDstPix++; } } } else { // 4 chanels for (y= yIni; y< yLim; y++) { pSrcPix= (unsigned char *) crvImgOffset (pImgSrc, xIni, y); pDstPix= (unsigned char *) crvImgOffset (pImgDst, xIni, y); for (x= xIni; x< xLim; x++) { sum= *pSrcPix; pSrcPix++; // B sum+= *pSrcPix; pSrcPix++; // G sum+= *pSrcPix; pSrcPix++; // R pSrcPix++; // A *pDstPix= (unsigned char) (sum / 3); pDstPix++; } } } }