Abstract
Figure D-1 provides a visualization of image texture using SDM’s.
You have full access to this open access chapter, Download chapter PDF
Keywords
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.
Listing D-1 illustrates the extended SDM metrics from Chapter 3. The code is available online at
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, >.xcentroid, fstream);
gtput(" ycentroid ", FXF, >.ycentroid, fstream);
gtput("low_frequency_coverage ", F3F, >.low_frequency_coverage, fstream);
gtput("total_coverage ", F3F, >.total_coverage, fstream);
gtput("corrected_coverage ", F3F, >.corrected_coverage, fstream);
gtput("total_power ", F3F, >.total_power, fstream);
gtput("relative_power ", F3F, >.relative_power, fstream);
gtput("locus_length ", FXF, >.locus_length, fstream);
gtput("locus_mean_density ", FXF, >.locus_mean_density, fstream);
gtput("bin_mean_density ", FXF, >.bin_mean_density, fstream);
gtput("containment ", F3F, >.containment, fstream);
gtput("linearity ", F3F, >.linearity, fstream);
gtput("linearity_strength ", F3F, >.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(>.low_frequency_coverage, d0, d90, d135, d45);
d0 = ( double )c0 / 0x10000;
d90 = ( double )c90 / 0x10000;
d135 = ( double )c135 / 0x10000;
d45 = ( double )c45 / 0x10000;
savegt(>.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(>.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(>.total_power, d0, d90, d135, d45);
d0 = (i0 / c0);
d90 = (i90 / c90);
d135 = (i135 / c135);
d45 = (i45 / c45);
savegt(>.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(>.locus_length, d0, d90, d135, d45);
d0 = (p0/c0);
d90 = (p90/c90);
d135 = (p135/c135);
d45 = (p45/c45);
savegt(>.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(>.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(>.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(>.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(>.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;
}
Author information
Authors and Affiliations
Rights and permissions
Open Access This chapter is licensed under the terms of the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License (http://creativecommons.org/licenses/by-nc-nd/4.0/), which permits any noncommercial use, sharing, distribution and reproduction in any medium or format, as long as you give appropriate credit to the original author(s) and the source, provide a link to the Creative Commons licence and indicate if you modified the licensed material. You do not have permission under this licence to share adapted material derived from this chapter or parts of it.
The images or other third party material in this chapter are included in the chapter’s Creative Commons licence, unless indicated otherwise in a credit line to the material. If material is not included in the chapter’s Creative Commons licence and your intended use is not permitted by statutory regulation or exceeds the permitted use, you will need to obtain permission directly from the copyright holder.
Copyright information
© 2014 Scott Krig
About this chapter
Cite this chapter
Krig, S. (2014). Extended SDM Metrics. In: Computer Vision Metrics. Apress, Berkeley, CA. https://doi.org/10.1007/978-1-4302-5930-5_12
Download citation
DOI: https://doi.org/10.1007/978-1-4302-5930-5_12
Published:
Publisher Name: Apress, Berkeley, CA
Print ISBN: 978-1-4302-5929-9
Online ISBN: 978-1-4302-5930-5
eBook Packages: Professional and Applied ComputingProfessional and Applied Computing (R0)Apress Access Books