Advertisement

Extended SDM Metrics

  • Scott Krig
Open Access
Chapter

Abstract

Figure D-1 provides a visualization of image texture using SDM’s.

Keywords

Image Texture Document Preparation Char Form Pixel Data Type Conversion 
These keywords were added by machine and not by the authors. This process is experimental and the keywords may be updated as the learning algorithm improves.
Figure D-1 provides a visualization of image texture using SDM’s.
Figure D-1.

SDM extended metrics

Listing D-1 illustrates the extended SDM metrics from  Chapter 3. The code is available online at

http://www.apress.com/source-code/ComputerVisionMetrics

Listing D-1. Extended SDM Metrics from  Chapter 3

/*

**        CREATED 1991 (C) KRIG RESEARCH, SCOTT KRIG - UNPUBLISHED SOFTWARE

**        PORTED TO MAC 2014

**

**                        ALL RIGHTS RESERVED

**

**        THIS SOFTWARE MAY BE USED FREELY FOR ACADEMIC AND RESEARCH PURPOSES.

**        REFERENCE THIS BOOK AND PROVIDE THIS NOTICE WHEN USING THE SOFTWARE.

*/

using namespace std;

#include <math.h>

#include <stdio.h>

#include <opencv2/opencv.hpp>

#include "/usr/local/include/opencv/cv.h"

#include "/usr/local/include/opencv2/core/core.hpp"

#include "/usr/local/include/opencv2/highgui/highgui.hpp"

#include <iostream>

using namespace cv;

#define TINY       0.0000000001

#define F6U        "%6f.3"

#define F6F        "%.6f"

#define F3F        "%.3f"

#define FXF        "%.0f"

#define FALSE 0

#define TRUE 1

typedef struct area {

        int x;

        int y;

        int dx;

        int dy;

} area_t;

typedef struct {

        double        t0;

        double        t90;

        double        t135;

        double        t45;

        double        tave;

        } ctab;

typedef struct {

        double        median;

        double        ave;

        double        adev;

        double        sdev;

        double        svar;

        double        skew;

        double        curt;

        int           min;

        int           max;

        ctab          xcentroid;

        ctab          ycentroid;

        ctab          _asm;

        ctab          low_frequency_coverage;

        ctab          total_coverage;

        ctab          corrected_coverage;

        ctab          total_power;

        ctab          relative_power;

        ctab          locus_length;

        ctab          locus_mean_density;

        ctab          bin_mean_density;

        ctab          containment;

        ctab          linearity;

        ctab          linearity_strength;

        ctab          autocorrelation;

        ctab          covariance;

        ctab          inertia; /* haralick contrast */

        ctab          absolute_value;

        ctab          inverse_difference; /* haralick */

        ctab          entropy; /* haralick */

        ctab          correlation; /* haralick */

        } glob_t;

glob_t        gt;

/* FUNCTIONS */

int i_sort (

int        *x,

int        n,

int        parm)

{

           int        k,i,ii;

           int        y,found;

           int        xi;

           int        n2, n2p;

           x--;

           for (k=1; k<n+1; k++) {

                   y = x[k];

                   for (i=k-1, found = FALSE; i>=0 && !found; ) {

                           xi = x[i];

                           ii = i+1;

                           if (y < xi) {

                                   x[ii] = xi;

                                   i--;

                           } else {

                                   found = TRUE;

                           }

                   }

                   x[ii] = y;

           }

           if (parm == 0) return 0;

           n2p = (n2=(n>>1))+1;

           return ( n % 2 ? x[n2p] : (x[n2] + x[n2p]) >>1 );

}

int lmoment (

int        *data,

int        n,

double     *median,

double     *ave,

double     *adev,

double     *sdev,

double     *svar,

double     *skew,

double     *curt)

{

        int        j;

        double     s,p,ep=0.0;

        if (n <= 1) return 0;

        s=0.0;

        for (j=1; j<=n;j++) s += ( double )data[j];

        *ave=s/n;

        *adev=(*svar)=(*skew)=(*curt)=0.0;

        for (j=1;j<=n;j++) {

                *adev += abs(s=( double )data[j]-(*ave));

                *svar += (p=s*s);

                *skew += (p *= s);

                *curt += (p *= s);

        }

        *adev /=n;

        *svar = (*svar - ep*ep / n) / (n-1);

        *sdev= sqrt (*svar);

        if (*svar) {

                s = (n*(*svar)*(*sdev));

                if (s != 0) *skew /=s;

                else *skew = 0;

                s = (n*(*svar)*(*svar))-3.0;

                if (s != 0) *curt = (*curt) / s;

                else *curt = 0;

        } else {

                *skew = *curt = 0.0;

        }

        *median = 0;

        if (n > 20000) return 0;

        *median = ( double )i_sort(data, n, 1);

        return 0;

}

int        mean_sdev (

int        xp,

int        yp,

int        *xdata,

double     *xmean,

double     *xsdev,

double     *ymean,

double     *ysdev)

{

        double     u_x1, a_x1;

        int        mx, my,v,t,x,y,z, offset;

        int        dif[256];

        /* first calculate mean */

        offset = 256 * yp;

        x = y = 0;

        for (z=0; z < 256; x += xdata[offset+z], z++);

        for (z=0; z < 256; y += xdata[xp + (z*256)], z++);

        mx = x / 256.;

        *xmean = ( double )mx;

        my = y / 256.;

        *ymean = ( double )my;

        /* now calculate standard deviation */

        x = y = 0;

        z=0;

        while (z < 256) {

                v = mx - xdata[offset+z];

                x += v*v;

                v = my - xdata[xp + (z*256)];

                y += v*v;

                z++;

        }

        *xsdev = x / 256;

        *ysdev = y / 256;

        return 0;

}

int lohi (

int     n,

int     *cv,

int     *lo,

int     *hi)

{

        int        x;

        int        lv, hv;

        lv = 0x1fffff;

        hv =0;

        x=0;

        while (x < n) {

                if (cv[x] < lv) lv = cv[x];

                if (cv[x] > hv) hv = cv[x];

                x++;

        }

        *lo = lv;

        *hi = hv;

        return 0;

}

int        savegt (

ctab       *ctp,

double     dv1,

double dv2,

double dv3,

double dv4)

{

        ctp->t0 = dv1;

        ctp->t90 = dv2;

        ctp->t135 = dv3;

        ctp->t45 = dv4;

        ctp->tave = (dv1 + dv2 + dv3 + dv4) / 4;

        return 0;

}

int     gtput (

char    *prompt,

char    *fs,

ctab    *ctp,

FILE    *fstream)

{

        char        str[256];

        char        form[256];

        fputs (prompt, fstream);

        sprintf (form, "%s       %s    %s    %s    %s \n", fs, fs, fs, fs, fs);

        sprintf (str, form, ctp->t0, ctp->t90, ctp->t135, ctp->t45, ctp->tave);

        fputs (str, fstream);

        return 0;

}

int     put_txfile (

FILE    *fstream)

{

        char        str[256];

        sprintf (str, "gray value moments: min :%u max:%u mean:%u\n",gt.min,gt.max, ( int )gt.ave);

        fputs (str, fstream);

        sprintf (str, "moments:  adev :%.4f  sdev :%.4f  svar :%.4f  skew:%.6f  curt:%.6f \n",

gt.adev, gt.sdev, gt.svar, gt.skew, gt.curt);

        fputs (str, fstream);

        fputs ("\n", fstream);

        fputs ("         --------------------------------------\n", fstream);

        fputs ("            0deg   90deg   135deg   45deg   ave \n", fstream);

        fputs ("         --------------------------------------\n", fstream);

        gtput(" xcentroid               ", FXF, &gt.xcentroid, fstream);

        gtput(" ycentroid               ", FXF, &gt.ycentroid, fstream);

        gtput("low_frequency_coverage  ", F3F, &gt.low_frequency_coverage, fstream);

        gtput("total_coverage          ", F3F, &gt.total_coverage, fstream);

        gtput("corrected_coverage        ", F3F, &gt.corrected_coverage, fstream);

        gtput("total_power             ", F3F, &gt.total_power, fstream);

        gtput("relative_power           ", F3F, &gt.relative_power, fstream);

        gtput("locus_length            ", FXF, &gt.locus_length, fstream);

        gtput("locus_mean_density        ", FXF, &gt.locus_mean_density, fstream);

        gtput("bin_mean_density          ", FXF, &gt.bin_mean_density, fstream);

        gtput("containment             ", F3F, &gt.containment, fstream);

        gtput("linearity               ", F3F, &gt.linearity, fstream);

        gtput("linearity_strength        ", F3F, &gt.linearity_strength, fstream);

        return 0;

}

int     texture (

char    *filename)

{

        char        str[256];

        int        pmx[256], pmy[256];

        int        x,y,z,dx,dy,dz,sz,bpp;

        int        accum, tmin, tmax;

        int        tmin2, tmax2, yc;

        int        *data;

        int        mval0, mval90, mval135, mval45;

        double  median, ave, adev, sdev, svar, skew, curt;

        double  median2, ave2, adev2, sdev2, svar2, skew2, curt2;

        int        *dm0, *dm90, *dm135, *dm45;

        FILE       *fstream;

        int        i0, i90, i135, i45, iave, n;

        int        c0, c90, c135, c45, cave;

        int        p0, p90, p135, p45, pave;

        double     d0, d90, d135, d45, dave;

        double     f0, f90, f135, f45;

        /**************************************************************/

        /* READ THE INPUT IMAGE, EXPECT IT TO BE 8-bit UNSIGNED INT   */

        /* Mat type conversion is simple in openCV, try it later      */

        Mat imageIn = cv::imread(filename);

        dx = imageIn.rows;

        dy = imageIn.cols;

        unsigned char *pixels = imageIn.data;

        cout << " dx " << dx << " dy " << dy << " elemSize() " << imageIn.elemSize() << endl ;

        data = ( int *) malloc (dx * dy * 4);

        if (data == 0)

        {

                cout << " malloc error in texture()" << endl ;

        }

        for (y=0; y < dy; y++) {

                for (x=0; x < dx; x++) {

                        int pixel = ( int )*(imageIn.ptr(x,y));

                        if (pixel > 255) { pixel = 255; }

                        data[(y * dx) + x] = pixel;

                }

        }

        /**********************************************************/

        /* PART 1 - get normal types of statistics from pixel data */

        lmoment(data, sz, &median, &ave, &adev, &sdev, &svar, &skew, &curt);

        lohi(sz, data, &tmin, &tmax);

        gt.median = median;

        gt.ave = ave;

        gt.adev = adev;

        gt.sdev = sdev;

        gt.svar = svar;

        gt.skew = skew;

        gt.curt = curt;

        gt.min = tmin;

        gt.max = tmax;

        fstream = fopen ("SDMExtended.txt", "w");

        if (fstream <= 0) {

                cout << "#cannot create file" << endl ;

                return 0;

        }

        sprintf (str, "texture for object:     %s\n", filename);

        fputs (str, fstream);

        sprintf (str, "area:                   %u, %u \n", dx, dy);

        fputs (str, fstream);

        /**********************************************************/

        /* PART 2 - calculate the 4 spatial dependency matricies */

        dm0   = ( int *) malloc ( 256*256*4 );

        dm90  = ( int *) malloc ( 256*256*4 );

        dm135 = ( int *) malloc ( 256*256*4 );

        dm45  = ( int *) malloc ( 256*256*4 );

        if ((dm0==0) || (dm90==0) || (dm135==0) || (dm45==0)) {

                cout << " malloc error in texture2" << endl ;

                return 0;

        }

        x=0;

        while (x < 256*256) {

                dm0[x] = dm90[x] = dm135[x] = dm45[x] = 0;

                x++;

        }

        y=0;

        while (y < dy-1) {

                yc = dx * y;

                x=0;

                while (x < dx-1) {

                  dm0[ (data[yc + x]&0xff) + ((( data[yc + x + 1]  )<< 8)&0xff00) ]++;

                  dm0[ (data[yc + x + 1]&0xff) + ((( data[yc + x]  )<< 8)&0xff00) ]++;

                  dm90[ (data[yc + x]&0xff) + ((( data[yc + x + dx]  )<< 8)&0xff00) ]++;

                  dm90[ (data[yc + x + dx]&0xff) + ((( data[yc + x]  )<< 8)&0xff00) ]++;

                  dm135[ (data[yc + x]&0xff) + ((( data[yc + x + dx + 1]  )<< 8)&0xff00) ]++;

                  dm135[ (data[yc + x + dx + 1]&0xff) + ((( data[yc + x]  )<< 8)&0xff00) ]++;

                  dm45[ (data[yc + x + 1]&0xff) + ((( data[yc + x + dx]  )<< 8)&0xff00) ]++;

                  dm45[ (data[yc + x + dx]&0xff) + ((( data[yc + x + 1]  )<< 8)&0xff00) ]++;

                        x++;

                }

                y++;

        }

        /***************** CALCULATE TEXTURE METRICS ******************/

        /* centroid */

        pmx[0] = pmx[1] = pmx[2] = pmx[3] = 0;

        pmy[0] = pmy[1] = pmy[2] = pmy[3] = 0;

        i0 = i90 = i135 = i45 = 0;

        y=0;

        while (y < 256) {

                x=0;

                while (x < 256) {

                        z = x + (256 * y);

                        pmx[0] += (x * dm0[z]);

                        pmy[0] += (y * dm0[z]); i0 += dm0[z];

                        pmx[1] += (x * dm90[z]);

                        pmy[1] += (y * dm90[z]); i90 += dm90[z];

                        pmx[2] += (x * dm135[z]);

                        pmy[2] += (y * dm135[z]); i135 += dm135[z];

                        pmx[3] += (x * dm45[z]);

                        pmy[3] += (y * dm45[z]); i45 += dm45[z];

                        x++;

                }

                y++;

        }

        pmx[0] = pmx[0] / i0;

        pmy[0] = pmy[0] / i0;

        pmx[1] = pmx[1] / i90;

        pmy[1] = pmy[1] / i90;

        pmx[2] = pmx[2] / i135;

        pmy[2] = pmy[2] / i135;

        pmx[3] = pmx[3] / i45;

        pmy[3] = pmy[3] / i45;

        x = (pmx[0] + pmx[1] + pmx[2] + pmx[3]) / 4;

        y = (pmy[0] + pmy[1] + pmy[2] + pmy[3]) / 4;

        gt.xcentroid.t0 = pmx[0];

        gt.ycentroid.t0 = pmy[0];

        gt.xcentroid.t90 = pmx[1];

        gt.ycentroid.t90 = pmy[1];

        gt.xcentroid.t135 = pmx[2];

        gt.ycentroid.t135 = pmy[2];

        gt.xcentroid.t45 = pmx[3];

        gt.ycentroid.t45 = pmy[3];

        gt.xcentroid.tave = x;

        gt.ycentroid.tave = y;

        /* low frequency coverage */

        i0 = i90 = i135 = i45 = 0;

        c0 = c90 = c135 = c45 = 0;

        x=0;

        while (x < 256*256) {

                if ((dm0[x] != 0) && (dm0[x] < 3)) i0++;

                if ((dm90[x] != 0) && (dm90[x] < 3)) i90++;

                if ((dm135[x] != 0) && (dm135[x] < 3)) i135++;

                if ((dm45[x] != 0) && (dm45[x] < 3)) i45++;

                if (!dm0[x]) c0++;

                if (!dm90[x]) c90++;

                if (!dm135[x]) c135++;

                if (!dm45[x]) c45++;

                x++;

        }

        d0 = ( double )i0 / 0x10000;

        d90 = ( double )i90 / 0x10000;

        d135 = ( double )i135 / 0x10000;

        d45 = ( double )i45 / 0x10000;

        savegt(&gt.low_frequency_coverage, d0, d90, d135, d45);

        d0 = ( double )c0 / 0x10000;

        d90 = ( double )c90 / 0x10000;

        d135 = ( double )c135 / 0x10000;

        d45 = ( double )c45 / 0x10000;

        savegt(&gt.total_coverage, d0, d90, d135, d45);

        d0 = (c0-i0) / ( double )0x10000;

        d90 = (c90-i90) / ( double )0x10000;

        d135 = (c135-i135) / ( double )0x10000;

        d45 = (c45-i45) / ( double )0x10000;

        savegt(&gt.corrected_coverage, d0, d90, d135, d45);

        /* power */

        i0 = i90 = i135 = i45 = 0;

        c0 = c90 = c135 = c45 = 0;

        p0 = p90 = p135 = p45 = 0;

        y=0;

        while (y < 256) {

                z = y * 256;

                x=0;

                while (x < 256) {

                        n = x-y;

                        if (n < 0) n = -n;

                        if (dm0[x+z] != 0) { i0 += n; c0++;  }

                        if (dm90[x+z] != 0) { i90 += n; c90++; }

                        if (dm135[x+z] != 0) { i135 += n; c135++; }

                        if (dm45[x+z] != 0) { i45 += n; c45++; }

                        x++;

                }

                y++;

        }

        d0 =  (i0 / 0x10000);

        d90 =  (i90 / 0x10000);

        d135 =  (i135 / 0x10000);

        d45 =  (i45 / 0x10000);

        savegt(&gt.total_power, d0, d90, d135, d45);

        d0 =  (i0 / c0);

        d90 =  (i90 / c90);

        d135 =  (i135 / c135);

        d45 =  (i45 / c45);

        savegt(&gt.relative_power, d0, d90, d135, d45);

        /* locus density */

        d0 = d90 = d135 = d45 = 0.0;

        c0 = c90 = c135 = c45 = 0;

        p0 = p90 = p135 = p45 = 0;

        y=0;

        while (y < 256) {

                z = y * 256;

                i0 = i90 = i135 = i45 = 0;

                x=0;

                while (x < 256) {

                   n = x-y;

                   if (n < 0) n = -n;

                   if ((dm0[x+z] != 0) && (n < 7)) { c0++; p0 += dm0[x+z]; }

                   if ((dm90[x+z] != 0) && (n < 7)) { c90++; p90 += dm90[x+z]; }

                   if ((dm135[x+z] != 0) && (n < 7)) { c135++; p135 += dm135[x+z]; }

                   if ((dm45[x+z] != 0) && (n < 7)) { c45++; p45 += dm45[x+z]; }

                   if ((dm0[x+z] == 0) && (n < 7)) { i0++; }

                   if ((dm90[x+z] == 0) && (n < 7)) { i90++; }

                   if ((dm135[x+z] == 0) && (n < 7)) { i135++; }

                   if ((dm45[x+z] == 0) && (n < 7)) { i45++; }

                   x++;

                }

                if (!i0) d0 += 1;

                if (!i90) d90 += 1;

                if (!i135) d135 += 1;

                if (!i45) d45 += 1;

                y++;

        }

        savegt(&gt.locus_length, d0, d90, d135, d45);

        d0 = (p0/c0);

        d90 = (p90/c90);

        d135 = (p135/c135);

        d45 = (p45/c45);

        savegt(&gt.locus_mean_density, d0, d90, d135, d45);

        /* density */

        c0 = c90 = c135 = c45 = 0;

        p0 = p90 = p135 = p45 = 0;

        x=0;

        while ( x < 256*256) {

                if (dm0[x] != 0) { c0 += dm0[x]; p0++; }

                if (dm90[x] != 0) { c90 += dm90[x]; p90++; }

                if (dm135[x] != 0) { c135 += dm135[x]; p135++; }

                if (dm45[x] != 0) { c45 += dm45[x]; p45++; }

                x++;

        }

        d0 = c0 / p0;

        d90 = c90 / p90;

        d135 = c135 / p135;

        d45 = c45 / p45;

        savegt(&gt.bin_mean_density, d0, d90, d135, d45);

        /* containment */

        i0 = i90 = i135 = i45 = 0;

        x=0;

        while (x < 256) {

                if (dm0[x]) i0++; if (dm0[256*256 - x - 1]) i0++;

                if (dm90[x]) i90++; if (dm90[256*256 - x - 1]) i90++;

                if (dm135[x]) i135++; if (dm135[256*256 - x - 1]) i135++;

                if (dm45[x]) i45++; if (dm45[256*256 - x - 1]) i45++;

                if (dm0[x*256]) i0++; if (dm0[(x*256)+255]) i0++;

                if (dm90[x*256]) i90++; if (dm90[(x*256)+255]) i90++;

                if (dm135[x*256]) i135++; if (dm135[(x*256)+255]) i135++;

                if (dm45[x*256]) i45++; if (dm45[(x*256)+255]) i45++;

         x++;

        }

        d0 = 1.0 - (( double )i0 / 1024.0);

        d90 = 1.0 - (( double )i90 / 1024.0);

        d135 = 1.0 - (( double )i135 / 1024.0);

        d45 = 1.0 - (( double )i45 / 1024.0);

        savegt(&gt.containment, d0, d90, d135, d45);

        /* linearity */

        i0 = i90 = i135 = i45 = 0;

        c0 = c90 = c135 = c45 = 0;

        y=0;

        while (y < 256) {

                z = y * 256;

                if (dm0[z + y] > 1) { i0++; c0 += dm0[z+y]; }

                if (dm90[z + y] > 1) { i90++; c90 += dm90[z+y]; }

                if (dm135[z + y] > 1) { i135++; c135 += dm135[z+y]; }

                if (dm45[z + y] > 1) { i45++; c45 += dm45[z+y]; }

                y++;

        }

        d0 = ( double )i0 / 256.;

        d90 = ( double )i90 / 256.;

        d135 = ( double )i135 / 256.;

        d45 = ( double )i45 / 256.;

        savegt(&gt.linearity, d0, d90, d135, d45);

        /* linearity strength */

        d0 = (c0/(i0+.00001)) / 256.;

        d90 = (c90/(i90+.00001)) / 256.;

        d135 = (c135/(i135+.00001)) / 256.;

        d45 = (c45/(i45+.00001)) / 256.;

        savegt(&gt.linearity_strength, d0, d90, d135, d45);

        /* WRITE ALL STATISTICS IN gt . STRUCTURE TO OUTPUT FILE */

        put_txfile(fstream);

        /*  clip to max value 255 */

        mval0 = mval90 = mval135 = mval45 = 0;

        x=0;

        while (x < 256*256) {

                if (dm0[x] > 255)  dm0[x] = 255;

                if (dm90[x] > 255)  dm90[x] = 255;

                if (dm135[x] > 255)  dm135[x] = 255;

                if (dm45[x] > 255)  dm45[x] = 255;

                x++;

        }

        /******************************************************/

        /* Convert data to unsigned char to write into png */

        unsigned char *dm0b   = ( unsigned char *) malloc ( 256*256);

        unsigned char *dm90b  = ( unsigned char *) malloc ( 256*256);

        unsigned char *dm135b = ( unsigned char *) malloc ( 256*256);

        unsigned char *dm45b  = ( unsigned char *) malloc ( 256*256);

        if ((dm0b==0) || (dm90b==0) || (dm135b==0) || (dm45b==0)) {

                cout << " malloc error in texture3" << endl ;

                return 0;

        }

        x=0;

        while (x < 256*256) {

                dm0b[x] = ( unsigned char ) (dm0[x] & 0xff);

                dm90b[x] = ( unsigned char ) (dm90[x] & 0xff);

                dm135b[x] = ( unsigned char ) (dm135[x] & 0xff);

                dm45b[x] = ( unsigned char ) (dm45[x] & 0xff);

                x++;

        }

        /*

        * write output to 4 quadrants:        0=0, 1=90, 2=135, 3=145

        */

        char outfile[256];

        sprintf (outfile, "%s_SDMQUadrant_0deg_8UC1. png ", filename);

        Mat SDMQuadrant0(256, 256, CV_8UC1, dm0b);

        imwrite(outfile, SDMQuadrant0);

        sprintf (outfile, "%s_SDMQUadrant_90deg_8UC1. png ", filename);

        Mat SDMQuadrant90(256, 256, CV_8UC1, dm90b);

        imwrite(outfile, SDMQuadrant90);

        sprintf (outfile, "%s_SDMQUadrant_135deg_8UC1. png ", filename);

        Mat SDMQuadrant135(256, 256, CV_8UC1, dm135b);

        imwrite(outfile, SDMQuadrant135);

        sprintf (outfile, "%s_SDMQUadrant_45deg_8UC1. png ", filename);

        Mat SDMQuadrant45(256, 256, CV_8UC1, dm45b);

        imwrite(outfile, SDMQuadrant45);

        free (dm0);

        free (dm90);

        free (dm135);

        free (dm45);

        free (data);

        free (dm0b);

        free (dm90b);

        free (dm135b);

        free (dm45b);

        fclose (fstream);

        return 0;

}

int main ( int argc, char **argv)

{

        cout << "8-bit unsigned image expected as input" << endl ;

        texture (argv[1]);

        return 0;

}

Copyright information

© Scott Krig 2014

Authors and Affiliations

  • Scott Krig
    • 1
  1. 1.CAUS

Personalised recommendations