TEXTURE * Extract_Texture_Features(int distance, register gray **grays, int rows, int cols, TEXTURE_FEATURE_MAP *feature_usage) { FILE *ifp; register gray *gP; int tone[PGM_MAXMAXVAL+1], R0, R45, R90, R135, angle, d = 1, x, y; int argn, bps, padright, row, col, i; int itone, jtone, tones,g_val; float **P_matrix0, **P_matrix45, **P_matrix90, **P_matrix135; float ASM[4], contrast[4], corr[4], var[4], idm[4], savg[4]; float sentropy[4], svar[4], entropy[4], dvar[4], dentropy[4]; float icorr[4], maxcorr[4]; float *Tp; gray nmaxval, maxval; char *usage = "[-d <d>] [pgmfile]"; TEXTURE *Texture; Texture = (TEXTURE *) calloc(1,sizeof(TEXTURE)); if(!Texture) { printf("\nERROR in TEXTURE structure allocate\n"); exit(1); } d = distance; /* Determine the number of different gray scales (not maxval) */ for (row = PGM_MAXMAXVAL; row >= 0; --row) tone[row] = -1; for (row = rows - 1; row >= 0; --row) for (col = 0; col < cols; ++col) { /* if (grays[row][col]) If gray value equal 0 don't include */ tone[grays[row][col]] = grays[row][col]; } for (row = PGM_MAXMAXVAL, tones = 0; row >= 0; --row) if (tone[row] != -1) tones++; /* fprintf (stderr, "(Image has %d graylevels.)\n", tones); */ /* Collapse array, taking out all zero values */ for (row = 0, itone = 0; row <= PGM_MAXMAXVAL; row++) if (tone[row] != -1) tone[itone++] = tone[row]; /* Now array contains only the gray levels present (in ascending order) */ /* Allocate memory for gray-tone spatial dependence matrix */ P_matrix0 = pgm_matrix (0, tones, 0, tones); P_matrix45 = pgm_matrix (0, tones, 0, tones); P_matrix90 = pgm_matrix (0, tones, 0, tones); P_matrix135 = pgm_matrix (0, tones, 0, tones); for (row = 0; row < tones; ++row) for (col = 0; col < tones; ++col) { P_matrix0[row][col] = P_matrix45[row][col] = 0; P_matrix90[row][col] = P_matrix135[row][col] = 0; } R0 = 0; R45 = 0; R90 = 0; R135 = 0; /* Find gray-tone spatial dependence matrix */ /* fprintf (stderr, "(Computing spatial dependence matrix..."); */ for (row = 0; row < rows; ++row) for (col = 0; col < cols; ++col) /* if (grays[row][col]) */ for (x = 0, angle = 0; angle <= 135; angle += 45) { while (tone[x] != grays[row][col]) x++; /* M. Boland if (angle == 0 && col + d < cols) */ /* M. Boland - include neighbor only if != 0 */ if (angle == 0 && col + d < cols && grays[row][col + d]) { y = 0; while (tone[y] != grays[row][col + d]) y++; P_matrix0[x][y]++; P_matrix0[y][x]++; /* R0++; M. Boland 25 Nov 98 */ R0+=2 ; } /* M. Boland if (angle == 90 && row + d < rows) */ /* M. Boland - include neighbor only if != 0 */ else if (angle == 90 && row + d < rows && grays[row + d][col]) { y = 0; while (tone[y] != grays[row + d][col]) y++; P_matrix90[x][y]++; P_matrix90[y][x]++; /* R90++; M. Boland 25 Nov 98 */ R90+=2 ; } /* M. Boland if (angle == 45 && row + d < rows && col - d >= 0) */ /* M. Boland - include neighbor only if != 0 */ else if (angle == 45 && row + d < rows && col - d >= 0 && grays[row + d][col - d]) { y = 0; while (tone[y] != grays[row + d][col - d]) y++; P_matrix45[x][y]++; P_matrix45[y][x]++; /* R45++; M. Boland 25 Nov 98 */ R45+=2 ; } /* M. Boland if (angle == 135 && row + d < rows && col + d < cols) */ else if (angle == 135 && row + d < rows && col + d < cols && grays[row + d][col + d]) { y = 0; while (tone[y] != grays[row + d][col + d]) y++; P_matrix135[x][y]++; P_matrix135[y][x]++; /* R135++; M. Boland 25 Nov 98 */ R135+=2 ; } } /* Gray-tone spatial dependence matrices are complete */ /* Find normalizing constants */ /* R0 = 2 * rows * (cols - 1); R45 = 2 * (rows - 1) * (cols - 1); R90 = 2 * (rows - 1) * cols; R135 = R45; */ /* Normalize gray-tone spatial dependence matrix */ for (itone = 0; itone < tones; ++itone) for (jtone = 0; jtone < tones; ++jtone) { P_matrix0[itone][jtone] /= R0; P_matrix45[itone][jtone] /= R45; P_matrix90[itone][jtone] /= R90; P_matrix135[itone][jtone] /= R135; } /* fprintf (stderr, " done.)\n"); */ /* fprintf (stderr, "(Computing textural features"); */ /* fprintf (stdout, "\n"); */ /* DOT; */ /* fprintf (stdout, "%s 0 45 90 135 Avg Range\n", BL); */ if (feature_usage->ASM) { ASM[0] = f1_asm (P_matrix0, tones); ASM[1] = f1_asm (P_matrix45, tones); ASM[2] = f1_asm (P_matrix90, tones); ASM[3] = f1_asm (P_matrix135, tones); } Tp = &Texture->ASM[0]; results (Tp, F1, ASM); if (feature_usage->contrast) { contrast[0] = f2_contrast (P_matrix0, tones); contrast[1] = f2_contrast (P_matrix45, tones); contrast[2] = f2_contrast (P_matrix90, tones); contrast[3] = f2_contrast (P_matrix135, tones); } Tp = &Texture->contrast[0]; results (Tp, F2, contrast); if (feature_usage->correlation) { corr[0] = f3_corr (P_matrix0, tones); corr[1] = f3_corr (P_matrix45, tones); corr[2] = f3_corr (P_matrix90, tones); corr[3] = f3_corr (P_matrix135, tones); } Tp = &Texture->correlation[0]; results (Tp, F3, corr); if (feature_usage->variance) { var[0] = f4_var (P_matrix0, tones); var[1] = f4_var (P_matrix45, tones); var[2] = f4_var (P_matrix90, tones); var[3] = f4_var (P_matrix135, tones); } Tp = &Texture->variance[0]; results (Tp, F4, var); if (feature_usage->IDM) { idm[0] = f5_idm (P_matrix0, tones); idm[1] = f5_idm (P_matrix45, tones); idm[2] = f5_idm (P_matrix90, tones); idm[3] = f5_idm (P_matrix135, tones); } Tp = &Texture->IDM[0]; results (Tp, F5, idm); if (feature_usage->sum_avg) { savg[0] = f6_savg (P_matrix0, tones); savg[1] = f6_savg (P_matrix45, tones); savg[2] = f6_savg (P_matrix90, tones); savg[3] = f6_savg (P_matrix135, tones); } Tp = &Texture->sum_avg[0]; results (Tp, F6, savg); if (feature_usage->sum_var) { sentropy[0] = f8_sentropy (P_matrix0, tones); sentropy[1] = f8_sentropy (P_matrix45, tones); sentropy[2] = f8_sentropy (P_matrix90, tones); sentropy[3] = f8_sentropy (P_matrix135, tones); } if (feature_usage->sum_entropy) { svar[0] = f7_svar (P_matrix0, tones, sentropy[0]); svar[1] = f7_svar (P_matrix45, tones, sentropy[1]); svar[2] = f7_svar (P_matrix90, tones, sentropy[2]); svar[3] = f7_svar (P_matrix135, tones, sentropy[3]); } Tp = &Texture->sum_var[0]; results (Tp, F7, svar); Tp = &Texture->sum_entropy[0]; results (Tp, F8, sentropy); if (feature_usage->entropy) { entropy[0] = f9_entropy (P_matrix0, tones); entropy[1] = f9_entropy (P_matrix45, tones); entropy[2] = f9_entropy (P_matrix90, tones); entropy[3] = f9_entropy (P_matrix135, tones); } Tp = &Texture->entropy[0]; results (Tp, F9, entropy); if (feature_usage->diff_var) { dvar[0] = f10_dvar (P_matrix0, tones); dvar[1] = f10_dvar (P_matrix45, tones); dvar[2] = f10_dvar (P_matrix90, tones); dvar[3] = f10_dvar (P_matrix135, tones); } Tp = &Texture->diff_var[0]; results (Tp, F10, dvar); if (feature_usage->diff_entropy) { dentropy[0] = f11_dentropy (P_matrix0, tones); dentropy[1] = f11_dentropy (P_matrix45, tones); dentropy[2] = f11_dentropy (P_matrix90, tones); dentropy[3] = f11_dentropy (P_matrix135, tones); } Tp = &Texture->diff_entropy[0]; results (Tp, F11, dentropy); if (feature_usage->meas_corr1) { icorr[0] = f12_icorr (P_matrix0, tones); icorr[1] = f12_icorr (P_matrix45, tones); icorr[2] = f12_icorr (P_matrix90, tones); icorr[3] = f12_icorr (P_matrix135, tones); } Tp = &Texture->meas_corr1[0]; results (Tp, F12, icorr); if (feature_usage->meas_corr2) { icorr[0] = f13_icorr (P_matrix0, tones); icorr[1] = f13_icorr (P_matrix45, tones); icorr[2] = f13_icorr (P_matrix90, tones); icorr[3] = f13_icorr (P_matrix135, tones); } Tp = &Texture->meas_corr2[0]; results (Tp, F13, icorr); if (feature_usage->max_corr_coef) { maxcorr[0] = f14_maxcorr (P_matrix0, tones); maxcorr[1] = f14_maxcorr (P_matrix45, tones); maxcorr[2] = f14_maxcorr (P_matrix90, tones); maxcorr[3] = f14_maxcorr (P_matrix135, tones); } /* M. Boland - 24 Nov 98 */ else { maxcorr[0] = 0 ; maxcorr[1] = 0 ; maxcorr[2] = 0 ; maxcorr[3] = 0 ; } Tp = &Texture->max_corr_coef[0]; results (Tp, F14, maxcorr); for (i=0; i<=tones; i++) free(P_matrix0[i]); for (i=0; i<=tones; i++) free(P_matrix45[i]); for (i=0; i<=tones; i++) free(P_matrix90[i]); for (i=0; i<=tones; i++) free(P_matrix135[i]); free(P_matrix0); free(P_matrix45); free(P_matrix90); free(P_matrix135); /* fprintf (stderr, " done.)\n"); */ return (Texture); /* exit (0);*/ }
int main (int argc, const char ** argv) { FILE * ifP; gray ** grays; unsigned int tone[PGM_MAXMAXVAL+1]; unsigned int r0, r45, r90; unsigned int d; unsigned int x, y; unsigned int row; int rows, cols; int argn; unsigned int itone; unsigned int toneCt; float ** p_matrix0, ** p_matrix45, ** p_matrix90, ** p_matrix135; float a2m[4], contrast[4], corr[4], var[4], idm[4], savg[4]; float sentropy[4], svar[4], entropy[4], dvar[4], dentropy[4]; float icorr[4], maxcorr[4]; gray maxval; unsigned int i; const char * const usage = "[-d <d>] [pgmfile]"; pm_proginit(&argc, argv); argn = 1; /* Check for flags. */ if ( argn < argc && argv[argn][0] == '-' ) { if ( argv[argn][1] == 'd' ) { ++argn; if ( argn == argc || sscanf( argv[argn], "%u", &d ) != 1 ) pm_usage( usage ); } else pm_usage( usage ); ++argn; } if ( argn < argc ) { ifP = pm_openr( argv[argn] ); ++argn; } else ifP = stdin; if ( argn != argc ) pm_usage( usage ); d = 1; grays = pgm_readpgm(ifP, &cols, &rows, &maxval); pm_close (ifP); /* Determine the number of different gray scales (not maxval) */ for (i = 0; i <= PGM_MAXMAXVAL; ++i) tone[i] = -1; for (row = 0; row < rows; ++row) { unsigned int col; for (col = 0; col < cols; ++col) tone[grays[row][col]] = grays[row][col]; } for (i = 0, toneCt = 0; i <= PGM_MAXMAXVAL; ++i) { if (tone[i] != -1) ++toneCt; } pm_message("(Image has %u gray levels.)", toneCt); /* Collapse array, taking out all zero values */ for (row = 0, itone = 0; row <= PGM_MAXMAXVAL; ++row) if (tone[row] != -1) tone[itone++] = tone[row]; /* Now array contains only the gray levels present (in ascending order) */ /* Allocate memory for gray-tone spatial dependence matrix */ p_matrix0 = matrix (0, toneCt, 0, toneCt); p_matrix45 = matrix (0, toneCt, 0, toneCt); p_matrix90 = matrix (0, toneCt, 0, toneCt); p_matrix135 = matrix (0, toneCt, 0, toneCt); for (row = 0; row < toneCt; ++row) { unsigned int col; for (col = 0; col < toneCt; ++col) { p_matrix0 [row][col] = p_matrix45 [row][col] = 0; p_matrix90[row][col] = p_matrix135[row][col] = 0; } } if (d > cols) pm_error("Image is narrower (%u columns) " "than specified distance (%u)", cols, d); /* Find gray-tone spatial dependence matrix */ pm_message("Computing spatial dependence matrix..."); for (row = 0; row < rows; ++row) { unsigned int col; for (col = 0; col < cols; ++col) { unsigned int angle; for (angle = 0, x = 0; angle <= 135; angle += 45) { while (tone[x] != grays[row][col]) ++x; if (angle == 0 && col + d < cols) { y = 0; while (tone[y] != grays[row][col + d]) ++y; ++p_matrix0[x][y]; ++p_matrix0[y][x]; } if (angle == 90 && row + d < rows) { y = 0; while (tone[y] != grays[row + d][col]) ++y; ++p_matrix90[x][y]; ++p_matrix90[y][x]; } if (angle == 45 && row + d < rows && col >= d) { y = 0; while (tone[y] != grays[row + d][col - d]) ++y; ++p_matrix45[x][y]; ++p_matrix45[y][x]; } if (angle == 135 && row + d < rows && col + d < cols) { y = 0; while (tone[y] != grays[row + d][col + d]) ++y; ++p_matrix135[x][y]; ++p_matrix135[y][x]; } } } } /* Gray-tone spatial dependence matrices are complete */ /* Find normalizing constants */ r0 = 2 * rows * (cols - d); r45 = 2 * (rows - d) * (cols - d); r90 = 2 * (rows - d) * cols; /* Normalize gray-tone spatial dependence matrix */ for (itone = 0; itone < toneCt; ++itone) { unsigned int jtone; for (jtone = 0; jtone < toneCt; ++jtone) { p_matrix0[itone][jtone] /= r0; p_matrix45[itone][jtone] /= r45; p_matrix90[itone][jtone] /= r90; p_matrix135[itone][jtone] /= r45; } } pm_message(" ...done."); pm_message("Computing textural features ..."); fprintf(stdout, "\n"); fprintf(stdout, "%s 0 45 90 135 Avg\n", BL); a2m[0] = f1_a2m(p_matrix0, toneCt); a2m[1] = f1_a2m(p_matrix45, toneCt); a2m[2] = f1_a2m(p_matrix90, toneCt); a2m[3] = f1_a2m(p_matrix135, toneCt); results(F1, a2m); contrast[0] = f2_contrast(p_matrix0, toneCt); contrast[1] = f2_contrast(p_matrix45, toneCt); contrast[2] = f2_contrast(p_matrix90, toneCt); contrast[3] = f2_contrast(p_matrix135, toneCt); results(F2, contrast); corr[0] = f3_corr(p_matrix0, toneCt); corr[1] = f3_corr(p_matrix45, toneCt); corr[2] = f3_corr(p_matrix90, toneCt); corr[3] = f3_corr(p_matrix135, toneCt); results(F3, corr); var[0] = f4_var(p_matrix0, toneCt); var[1] = f4_var(p_matrix45, toneCt); var[2] = f4_var(p_matrix90, toneCt); var[3] = f4_var(p_matrix135, toneCt); results(F4, var); idm[0] = f5_idm(p_matrix0, toneCt); idm[1] = f5_idm(p_matrix45, toneCt); idm[2] = f5_idm(p_matrix90, toneCt); idm[3] = f5_idm(p_matrix135, toneCt); results(F5, idm); savg[0] = f6_savg(p_matrix0, toneCt); savg[1] = f6_savg(p_matrix45, toneCt); savg[2] = f6_savg(p_matrix90, toneCt); savg[3] = f6_savg(p_matrix135, toneCt); results(F6, savg); svar[0] = f7_svar(p_matrix0, toneCt, savg[0]); svar[1] = f7_svar(p_matrix45, toneCt, savg[1]); svar[2] = f7_svar(p_matrix90, toneCt, savg[2]); svar[3] = f7_svar(p_matrix135, toneCt, savg[3]); results(F7, svar); sentropy[0] = f8_sentropy(p_matrix0, toneCt); sentropy[1] = f8_sentropy(p_matrix45, toneCt); sentropy[2] = f8_sentropy(p_matrix90, toneCt); sentropy[3] = f8_sentropy(p_matrix135, toneCt); results(F8, sentropy); entropy[0] = f9_entropy(p_matrix0, toneCt); entropy[1] = f9_entropy(p_matrix45, toneCt); entropy[2] = f9_entropy(p_matrix90, toneCt); entropy[3] = f9_entropy(p_matrix135, toneCt); results(F9, entropy); dvar[0] = f10_dvar(p_matrix0, toneCt); dvar[1] = f10_dvar(p_matrix45, toneCt); dvar[2] = f10_dvar(p_matrix90, toneCt); dvar[3] = f10_dvar(p_matrix135, toneCt); results(F10, dvar); dentropy[0] = f11_dentropy(p_matrix0, toneCt); dentropy[1] = f11_dentropy(p_matrix45, toneCt); dentropy[2] = f11_dentropy(p_matrix90, toneCt); dentropy[3] = f11_dentropy(p_matrix135, toneCt); results (F11, dentropy); icorr[0] = f12_icorr(p_matrix0, toneCt); icorr[1] = f12_icorr(p_matrix45, toneCt); icorr[2] = f12_icorr(p_matrix90, toneCt); icorr[3] = f12_icorr(p_matrix135, toneCt); results(F12, icorr); icorr[0] = f13_icorr(p_matrix0, toneCt); icorr[1] = f13_icorr(p_matrix45, toneCt); icorr[2] = f13_icorr(p_matrix90, toneCt); icorr[3] = f13_icorr(p_matrix135, toneCt); results(F13, icorr); maxcorr[0] = f14_maxcorr(p_matrix0, toneCt); maxcorr[1] = f14_maxcorr(p_matrix45, toneCt); maxcorr[2] = f14_maxcorr(p_matrix90, toneCt); maxcorr[3] = f14_maxcorr(p_matrix135, toneCt); results(F14, maxcorr); pm_message(" ...done."); return 0; }
float h_measure(int t_m) { switch (t_m) { /* Angular Second Moment */ case 1: return (f1_asm()); break; /* Contrast */ case 2: return (f2_contrast()); break; /* Correlation */ case 3: return (f3_corr()); break; /* Variance */ case 4: return (f4_var()); break; /* Inverse Diff Moment */ case 5: return (f5_idm()); break; /* Sum Average */ case 6: return (f6_savg()); break; /* Sum Variance */ case 7: return (f7_svar()); break; /* Sum Entropy */ case 8: return (f8_sentropy()); break; /* Entropy */ case 9: return (f9_entropy()); break; /* Difference Variance */ case 10: return (f10_dvar()); break; /* Difference Entropy */ case 11: return (f11_dentropy()); break; /* Measure of Correlation-1 */ case 12: return (f12_icorr()); break; /* Measure of Correlation-2 */ case 13: return (f13_icorr()); break; } return 0; }
TEXTURE * Extract_Texture_Features(int distance, int angle, register u_int8_t **grays, int rows, int cols, int max_val) { int tone_LUT[PGM_MAXMAXVAL+1]; /* LUT mapping gray tone(0-255) to matrix indicies */ int tone_count=0; /* number of tones actually in the img. atleast 1 less than 255 */ int itone; int row, col, i; double **P_matrix; double sum_entropy; TEXTURE *Texture; Texture = (TEXTURE *) calloc(1,sizeof(TEXTURE)); if (!Texture) { printf("\nERROR in TEXTURE structure allocate\n"); exit(1); } /* Determine the number of different gray tones (not maxval) */ for (row = PGM_MAXMAXVAL; row >= 0; --row) tone_LUT[row] = -1; for (row = rows - 1; row >= 0; --row) for (col = 0; col < cols; ++col) tone_LUT[grays[row][col]] = grays[row][col]; for (row = PGM_MAXMAXVAL, tone_count = 0; row >= 0; --row) if (tone_LUT[row] != -1) tone_count++; /* Use the number of different tones to build LUT */ for (row = 0, itone = 0; row <= PGM_MAXMAXVAL; row++) if (tone_LUT[row] != -1) tone_LUT[row] = itone++; /* compute gray-tone spatial dependence matrix */ if (angle == 0) P_matrix = CoOcMat_Angle_0 (distance, grays, rows, cols, tone_LUT, tone_count); else if (angle == 45) P_matrix = CoOcMat_Angle_45 (distance, grays, rows, cols, tone_LUT, tone_count); else if (angle == 90) P_matrix = CoOcMat_Angle_90 (distance, grays, rows, cols, tone_LUT, tone_count); else if (angle == 135) P_matrix = CoOcMat_Angle_135 (distance, grays, rows, cols, tone_LUT, tone_count); else { fprintf (stderr, "Cannot created co-occurence matrix for angle %d. Unsupported angle.\n", angle); return NULL; } /* compute the statistics for the spatial dependence matrix */ Texture->ASM = f1_asm (P_matrix, tone_count); Texture->contrast = f2_contrast (P_matrix, tone_count); Texture->correlation = f3_corr (P_matrix, tone_count); Texture->variance = f4_var (P_matrix, tone_count); Texture->IDM = f5_idm (P_matrix, tone_count); Texture->sum_avg = f6_savg (P_matrix, tone_count); /* T.J.M watch below the cast from float to double */ sum_entropy = f8_sentropy (P_matrix, tone_count); Texture->sum_entropy = sum_entropy; Texture->sum_var = f7_svar (P_matrix, tone_count, sum_entropy); Texture->entropy = f9_entropy (P_matrix, tone_count); Texture->diff_var = f10_dvar (P_matrix, tone_count); Texture->diff_entropy = f11_dentropy (P_matrix, tone_count); Texture->meas_corr1 = f12_icorr (P_matrix, tone_count); Texture->meas_corr2 = f13_icorr (P_matrix, tone_count); Texture->max_corr_coef = f14_maxcorr (P_matrix, tone_count); return (Texture); }