16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M///////////////////////////////////////////////////////////////////////////////////////
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  By downloading, copying, installing or using the software you agree to this license.
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  If you do not agree to this license, do not download, install,
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  copy or use the software.
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                        Intel License Agreement
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                For Open Source Computer Vision Library
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2000, Intel Corporation, all rights reserved.
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective owners.
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification,
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met:
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's of source code must retain the above copyright notice,
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer.
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's in binary form must reproduce the above copyright notice,
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer in the documentation
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     and/or other materials provided with the distribution.
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * The name of Intel Corporation may not be used to endorse or promote products
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     derived from this software without specific prior written permission.
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed.
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct,
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services;
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability,
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage.
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      Calculation of a texture descriptors from GLCM (Grey Level Co-occurrence Matrix'es)
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      The code was submitted by Daniel Eaton [danieljameseaton@yahoo.com]
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cvaux.h"
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <math.h>
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <assert.h>
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_MAX_NUM_GREY_LEVELS_8U  256
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstruct CvGLCM
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int matrixSideLength;
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int numMatrices;
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double*** matrices;
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  numLookupTableElements;
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  forwardLookupTable[CV_MAX_NUM_GREY_LEVELS_8U];
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  reverseLookupTable[CV_MAX_NUM_GREY_LEVELS_8U];
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double** descriptors;
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int numDescriptors;
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int descriptorOptimizationType;
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int optimizationType;
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvCreateGLCM_LookupTable_8u_C1R( const uchar* srcImageData, int srcImageStep,
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                             CvSize srcImageSize, CvGLCM* destGLCM,
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                             int* steps, int numSteps, int* memorySteps );
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvCreateGLCMDescriptors_AllowDoubleNest( CvGLCM* destGLCM, int matrixIndex );
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvGLCM*
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCreateGLCM( const IplImage* srcImage,
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              int stepMagnitude,
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              const int* srcStepDirections,/* should be static array..
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                          or if not the user should handle de-allocation */
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              int numStepDirections,
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              int optimizationType )
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    static const int defaultStepDirections[] = { 0,1, -1,1, -1,0, -1,-1 };
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* memorySteps = 0;
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGLCM* newGLCM = 0;
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* stepDirections = 0;
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCreateGLCM" );
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar* srcImageData = 0;
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize srcImageSize;
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int srcImageStep;
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int stepLoop;
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int maxNumGreyLevels8u = CV_MAX_NUM_GREY_LEVELS_8U;
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !srcImage )
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( srcImage->nChannels != 1 )
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_BadNumChannels, "Number of channels must be 1");
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( srcImage->depth != IPL_DEPTH_8U )
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_BadDepth, "Depth must be equal IPL_DEPTH_8U");
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // no Directions provided, use the default ones - 0 deg, 45, 90, 135
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !srcStepDirections )
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        srcStepDirections = defaultStepDirections;
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( stepDirections = (int*)cvAlloc( numStepDirections*2*sizeof(stepDirections[0])));
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memcpy( stepDirections, srcStepDirections, numStepDirections*2*sizeof(stepDirections[0]));
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvGetImageRawData( srcImage, &srcImageData, &srcImageStep, &srcImageSize );
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // roll together Directions and magnitudes together with knowledge of image (step)
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( memorySteps = (int*)cvAlloc( numStepDirections*sizeof(memorySteps[0])));
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( stepLoop = 0; stepLoop < numStepDirections; stepLoop++ )
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        stepDirections[stepLoop*2 + 0] *= stepMagnitude;
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        stepDirections[stepLoop*2 + 1] *= stepMagnitude;
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memorySteps[stepLoop] = stepDirections[stepLoop*2 + 0]*srcImageStep +
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                stepDirections[stepLoop*2 + 1];
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( newGLCM = (CvGLCM*)cvAlloc(sizeof(newGLCM)));
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( newGLCM, 0, sizeof(newGLCM) );
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    newGLCM->matrices = 0;
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    newGLCM->numMatrices = numStepDirections;
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    newGLCM->optimizationType = optimizationType;
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( optimizationType <= CV_GLCM_OPTIMIZATION_LUT )
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int lookupTableLoop, imageColLoop, imageRowLoop, lineOffset = 0;
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // if optimization type is set to lut, then make one for the image
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( optimizationType == CV_GLCM_OPTIMIZATION_LUT )
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( imageRowLoop = 0; imageRowLoop < srcImageSize.height;
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   imageRowLoop++, lineOffset += srcImageStep )
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( imageColLoop = 0; imageColLoop < srcImageSize.width; imageColLoop++ )
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    newGLCM->forwardLookupTable[srcImageData[lineOffset+imageColLoop]]=1;
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            newGLCM->numLookupTableElements = 0;
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( lookupTableLoop = 0; lookupTableLoop < maxNumGreyLevels8u; lookupTableLoop++ )
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( newGLCM->forwardLookupTable[ lookupTableLoop ] != 0 )
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    newGLCM->forwardLookupTable[ lookupTableLoop ] =
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        newGLCM->numLookupTableElements;
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    newGLCM->reverseLookupTable[ newGLCM->numLookupTableElements ] =
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        lookupTableLoop;
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    newGLCM->numLookupTableElements++;
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // otherwise make a "LUT" which contains all the gray-levels (for code-reuse)
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( optimizationType == CV_GLCM_OPTIMIZATION_NONE )
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( lookupTableLoop = 0; lookupTableLoop <maxNumGreyLevels8u; lookupTableLoop++ )
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                newGLCM->forwardLookupTable[ lookupTableLoop ] = lookupTableLoop;
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                newGLCM->reverseLookupTable[ lookupTableLoop ] = lookupTableLoop;
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            newGLCM->numLookupTableElements = maxNumGreyLevels8u;
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        newGLCM->matrixSideLength = newGLCM->numLookupTableElements;
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvCreateGLCM_LookupTable_8u_C1R( srcImageData, srcImageStep, srcImageSize,
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                          newGLCM, stepDirections,
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                          numStepDirections, memorySteps );
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( optimizationType == CV_GLCM_OPTIMIZATION_HISTOGRAM )
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadFlag, "Histogram-based method is not implemented" );
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /*  newGLCM->numMatrices *= 2;
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        newGLCM->matrixSideLength = maxNumGreyLevels8u*2;
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvCreateGLCM_Histogram_8uC1R( srcImageStep, srcImageSize, srcImageData,
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                       newGLCM, numStepDirections,
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                       stepDirections, memorySteps );
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    */
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &memorySteps );
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &stepDirections );
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 )
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &newGLCM );
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return newGLCM;
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvReleaseGLCM( CvGLCM** GLCM, int flag )
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvReleaseGLCM" );
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int matrixLoop;
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !GLCM )
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( *GLCM )
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT; // repeated deallocation: just skip it.
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (flag == CV_GLCM_GLCM || flag == CV_GLCM_ALL) && (*GLCM)->matrices )
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( matrixLoop = 0; matrixLoop < (*GLCM)->numMatrices; matrixLoop++ )
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( (*GLCM)->matrices[ matrixLoop ] )
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cvFree( (*GLCM)->matrices[matrixLoop] );
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cvFree( (*GLCM)->matrices + matrixLoop );
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &((*GLCM)->matrices) );
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (flag == CV_GLCM_DESC || flag == CV_GLCM_ALL) && (*GLCM)->descriptors )
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( matrixLoop = 0; matrixLoop < (*GLCM)->numMatrices; matrixLoop++ )
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvFree( (*GLCM)->descriptors + matrixLoop );
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &((*GLCM)->descriptors) );
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( flag == CV_GLCM_ALL )
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( GLCM );
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvCreateGLCM_LookupTable_8u_C1R( const uchar* srcImageData,
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  int srcImageStep,
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  CvSize srcImageSize,
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  CvGLCM* destGLCM,
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  int* steps,
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  int numSteps,
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  int* memorySteps )
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* stepIncrementsCounter = 0;
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvCreateGLCM_LookupTable_8u_C1R" );
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int matrixSideLength = destGLCM->matrixSideLength;
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int stepLoop, sideLoop1, sideLoop2;
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int colLoop, rowLoop, lineOffset = 0;
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double*** matrices = 0;
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // allocate memory to the matrices
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( destGLCM->matrices = (double***)cvAlloc( sizeof(matrices[0])*numSteps ));
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    matrices = destGLCM->matrices;
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( stepLoop=0; stepLoop<numSteps; stepLoop++ )
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( matrices[stepLoop] = (double**)cvAlloc( sizeof(matrices[0])*matrixSideLength ));
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( matrices[stepLoop][0] = (double*)cvAlloc( sizeof(matrices[0][0])*
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                  matrixSideLength*matrixSideLength ));
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memset( matrices[stepLoop][0], 0, matrixSideLength*matrixSideLength*
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                          sizeof(matrices[0][0]) );
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( sideLoop1 = 1; sideLoop1 < matrixSideLength; sideLoop1++ )
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            matrices[stepLoop][sideLoop1] = matrices[stepLoop][sideLoop1-1] + matrixSideLength;
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( stepIncrementsCounter = (int*)cvAlloc( numSteps*sizeof(stepIncrementsCounter[0])));
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( stepIncrementsCounter, 0, numSteps*sizeof(stepIncrementsCounter[0]) );
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // generate GLCM for each step
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( rowLoop=0; rowLoop<srcImageSize.height; rowLoop++, lineOffset+=srcImageStep )
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( colLoop=0; colLoop<srcImageSize.width; colLoop++ )
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int pixelValue1 = destGLCM->forwardLookupTable[srcImageData[lineOffset + colLoop]];
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( stepLoop=0; stepLoop<numSteps; stepLoop++ )
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int col2, row2;
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                row2 = rowLoop + steps[stepLoop*2 + 0];
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                col2 = colLoop + steps[stepLoop*2 + 1];
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( col2>=0 && row2>=0 && col2<srcImageSize.width && row2<srcImageSize.height )
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int memoryStep = memorySteps[ stepLoop ];
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int pixelValue2 = destGLCM->forwardLookupTable[ srcImageData[ lineOffset + colLoop + memoryStep ] ];
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    // maintain symmetry
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    matrices[stepLoop][pixelValue1][pixelValue2] ++;
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    matrices[stepLoop][pixelValue2][pixelValue1] ++;
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    // incremenet counter of total number of increments
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    stepIncrementsCounter[stepLoop] += 2;
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // normalize matrices. each element is a probability of gray value i,j adjacency in direction/magnitude k
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( sideLoop1=0; sideLoop1<matrixSideLength; sideLoop1++ )
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( sideLoop2=0; sideLoop2<matrixSideLength; sideLoop2++ )
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( stepLoop=0; stepLoop<numSteps; stepLoop++ )
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                matrices[stepLoop][sideLoop1][sideLoop2] /= double(stepIncrementsCounter[stepLoop]);
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    destGLCM->matrices = matrices;
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &stepIncrementsCounter );
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 )
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvReleaseGLCM( &destGLCM, CV_GLCM_GLCM );
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCreateGLCMDescriptors( CvGLCM* destGLCM, int descriptorOptimizationType )
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCreateGLCMDescriptors" );
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int matrixLoop;
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !destGLCM )
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !(destGLCM->matrices) )
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Matrices are not allocated" );
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvReleaseGLCM( &destGLCM, CV_GLCM_DESC ));
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( destGLCM->optimizationType != CV_GLCM_OPTIMIZATION_HISTOGRAM )
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        destGLCM->descriptorOptimizationType = destGLCM->numDescriptors = descriptorOptimizationType;
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadFlag, "Histogram-based method is not implemented" );
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      destGLCM->descriptorOptimizationType = destGLCM->numDescriptors = CV_GLCMDESC_OPTIMIZATION_HISTOGRAM;
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( destGLCM->descriptors = (double**)
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvAlloc( destGLCM->numMatrices*sizeof(destGLCM->descriptors[0])));
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( matrixLoop = 0; matrixLoop < destGLCM->numMatrices; matrixLoop ++ )
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( destGLCM->descriptors[ matrixLoop ] =
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                (double*)cvAlloc( destGLCM->numDescriptors*sizeof(destGLCM->descriptors[0][0])));
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memset( destGLCM->descriptors[matrixLoop], 0, destGLCM->numDescriptors*sizeof(double) );
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        switch( destGLCM->descriptorOptimizationType )
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            case CV_GLCMDESC_OPTIMIZATION_ALLOWDOUBLENEST:
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                icvCreateGLCMDescriptors_AllowDoubleNest( destGLCM, matrixLoop );
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            default:
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadFlag,
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                "descriptorOptimizationType different from CV_GLCMDESC_OPTIMIZATION_ALLOWDOUBLENEST\n"
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                "is not supported" );
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            /*
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            case CV_GLCMDESC_OPTIMIZATION_ALLOWTRIPLENEST:
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                icvCreateGLCMDescriptors_AllowTripleNest( destGLCM, matrixLoop );
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            case CV_GLCMDESC_OPTIMIZATION_HISTOGRAM:
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if(matrixLoop < destGLCM->numMatrices>>1)
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    icvCreateGLCMDescriptors_Histogram( destGLCM, matrixLoop);
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            */
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 )
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvReleaseGLCM( &destGLCM, CV_GLCM_DESC );
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvCreateGLCMDescriptors_AllowDoubleNest( CvGLCM* destGLCM, int matrixIndex )
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int sideLoop1, sideLoop2;
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int matrixSideLength = destGLCM->matrixSideLength;
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double** matrix = destGLCM->matrices[ matrixIndex ];
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double* descriptors = destGLCM->descriptors[ matrixIndex ];
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double* marginalProbability =
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (double*)cvAlloc( matrixSideLength * sizeof(marginalProbability[0]));
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( marginalProbability, 0, matrixSideLength * sizeof(double) );
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double maximumProbability = 0;
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double marginalProbabilityEntropy = 0;
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double correlationMean = 0, correlationStdDeviation = 0, correlationProductTerm = 0;
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( sideLoop1=0; sideLoop1<matrixSideLength; sideLoop1++ )
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int actualSideLoop1 = destGLCM->reverseLookupTable[ sideLoop1 ];
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( sideLoop2=0; sideLoop2<matrixSideLength; sideLoop2++ )
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double entryValue = matrix[ sideLoop1 ][ sideLoop2 ];
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int actualSideLoop2 = destGLCM->reverseLookupTable[ sideLoop2 ];
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int sideLoopDifference = actualSideLoop1 - actualSideLoop2;
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int sideLoopDifferenceSquared = sideLoopDifference*sideLoopDifference;
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            marginalProbability[ sideLoop1 ] += entryValue;
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            correlationMean += actualSideLoop1*entryValue;
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            maximumProbability = MAX( maximumProbability, entryValue );
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( actualSideLoop2 > actualSideLoop1 )
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                descriptors[ CV_GLCMDESC_CONTRAST ] += sideLoopDifferenceSquared * entryValue;
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            descriptors[ CV_GLCMDESC_HOMOGENITY ] += entryValue / ( 1.0 + sideLoopDifferenceSquared );
4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( entryValue > 0 )
4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                descriptors[ CV_GLCMDESC_ENTROPY ] += entryValue * log( entryValue );
4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            descriptors[ CV_GLCMDESC_ENERGY ] += entryValue*entryValue;
4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( marginalProbability>0 )
4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            marginalProbabilityEntropy += marginalProbability[ actualSideLoop1 ]*log(marginalProbability[ actualSideLoop1 ]);
4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    marginalProbabilityEntropy = -marginalProbabilityEntropy;
4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    descriptors[ CV_GLCMDESC_CONTRAST ] += descriptors[ CV_GLCMDESC_CONTRAST ];
4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    descriptors[ CV_GLCMDESC_ENTROPY ] = -descriptors[ CV_GLCMDESC_ENTROPY ];
4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    descriptors[ CV_GLCMDESC_MAXIMUMPROBABILITY ] = maximumProbability;
4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double HXY = 0, HXY1 = 0, HXY2 = 0;
4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    HXY = descriptors[ CV_GLCMDESC_ENTROPY ];
4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( sideLoop1=0; sideLoop1<matrixSideLength; sideLoop1++ )
4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double sideEntryValueSum = 0;
4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int actualSideLoop1 = destGLCM->reverseLookupTable[ sideLoop1 ];
4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( sideLoop2=0; sideLoop2<matrixSideLength; sideLoop2++ )
4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double entryValue = matrix[ sideLoop1 ][ sideLoop2 ];
4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sideEntryValueSum += entryValue;
4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int actualSideLoop2 = destGLCM->reverseLookupTable[ sideLoop2 ];
4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            correlationProductTerm += (actualSideLoop1 - correlationMean) * (actualSideLoop2 - correlationMean) * entryValue;
5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double clusterTerm = actualSideLoop1 + actualSideLoop2 - correlationMean - correlationMean;
5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            descriptors[ CV_GLCMDESC_CLUSTERTENDENCY ] += clusterTerm * clusterTerm * entryValue;
5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            descriptors[ CV_GLCMDESC_CLUSTERSHADE ] += clusterTerm * clusterTerm * clusterTerm * entryValue;
5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double HXYValue = marginalProbability[ actualSideLoop1 ] * marginalProbability[ actualSideLoop2 ];
5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( HXYValue>0 )
5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double HXYValueLog = log( HXYValue );
5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                HXY1 += entryValue * HXYValueLog;
5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                HXY2 += HXYValue * HXYValueLog;
5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        correlationStdDeviation += (actualSideLoop1-correlationMean) * (actualSideLoop1-correlationMean) * sideEntryValueSum;
5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    HXY1 =- HXY1;
5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    HXY2 =- HXY2;
5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    descriptors[ CV_GLCMDESC_CORRELATIONINFO1 ] = ( HXY - HXY1 ) / ( correlationMean );
5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    descriptors[ CV_GLCMDESC_CORRELATIONINFO2 ] = sqrt( 1.0 - exp( -2.0 * (HXY2 - HXY ) ) );
5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    correlationStdDeviation = sqrt( correlationStdDeviation );
5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    descriptors[ CV_GLCMDESC_CORRELATION ] = correlationProductTerm / (correlationStdDeviation*correlationStdDeviation );
5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    delete [] marginalProbability;
5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL double cvGetGLCMDescriptor( CvGLCM* GLCM, int step, int descriptor )
5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double value = DBL_MAX;
5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGetGLCMDescriptor" );
5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !GLCM )
5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !(GLCM->descriptors) )
5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (unsigned)step >= (unsigned)(GLCM->numMatrices))
5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "step is not in 0 .. GLCM->numMatrices - 1" );
5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (unsigned)descriptor >= (unsigned)(GLCM->numDescriptors))
5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "descriptor is not in 0 .. GLCM->numDescriptors - 1" );
5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    value = GLCM->descriptors[step][descriptor];
5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return value;
5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGetGLCMDescriptorStatistics( CvGLCM* GLCM, int descriptor,
5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               double* _average, double* _standardDeviation )
5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGetGLCMDescriptorStatistics" );
5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _average )
5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *_average = DBL_MAX;
5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _standardDeviation )
5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *_standardDeviation = DBL_MAX;
5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int matrixLoop, numMatrices;
5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double average = 0, squareSum = 0;
5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !GLCM )
5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !(GLCM->descriptors))
5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Descriptors are not calculated" );
5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (unsigned)descriptor >= (unsigned)(GLCM->numDescriptors) )
5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "Descriptor index is out of range" );
5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    numMatrices = GLCM->numMatrices;
5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( matrixLoop = 0; matrixLoop < numMatrices; matrixLoop++ )
5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double temp = GLCM->descriptors[ matrixLoop ][ descriptor ];
5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        average += temp;
5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        squareSum += temp*temp;
5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    average /= numMatrices;
5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _average )
5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *_average = average;
5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _standardDeviation )
6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *_standardDeviation = sqrt( (squareSum - average*average*numMatrices)/(numMatrices-1));
6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL IplImage*
6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCreateGLCMImage( CvGLCM* GLCM, int step )
6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    IplImage* dest = 0;
6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCreateGLCMImage" );
6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float* destData;
6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int sideLoop1, sideLoop2;
6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !GLCM )
6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !(GLCM->matrices) )
6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Matrices are not allocated" );
6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (unsigned)step >= (unsigned)(GLCM->numMatrices) )
6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "The step index is out of range" );
6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dest = cvCreateImage( cvSize( GLCM->matrixSideLength, GLCM->matrixSideLength ), IPL_DEPTH_32F, 1 );
6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    destData = (float*)(dest->imageData);
6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( sideLoop1 = 0; sideLoop1 < GLCM->matrixSideLength;
6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        sideLoop1++, (float*&)destData += dest->widthStep )
6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( sideLoop2=0; sideLoop2 < GLCM->matrixSideLength; sideLoop2++ )
6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double matrixValue = GLCM->matrices[step][sideLoop1][sideLoop2];
6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            destData[ sideLoop2 ] = (float)matrixValue;
6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 )
6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvReleaseImage( &dest );
6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return dest;
6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
649