//*************************************************************************** #include <iostream.h> #include <fstream.h> #include <stdlib.h> /* ANSI C standard library routines */ #include <string.h> /* ANSI standard string routines */ #include <limits.h> #include <math.h> #include <stdio.h> #include "image.h" //*************************************************************************** typedef struct mydiff_ { int value; int id; } mydiff; static int findknearest(int list[], int N, int k); //*************************************************************************** //static int compareIntegers (int *e1, int *e2) static int compareIntegers (const void *e1, const void *e2) { return (*((int *) e1) - *((int *) e2)); } //*************************************************************************** //static int compareIntegers2 (mydiff *e1, mydiff *e2) static int compareIntegers2 (const void *e1, const void *e2) { return (((mydiff *) e1)->value - ((mydiff *) e2)->value); } //*************************************************************************** void GrayImage::DilationNxN_Binary (int N, int num) // odd N { // num -> object with label "num" cout << " Applying " << N << "x" << N << " Dilation operator to component " << num << "..."; int dummy[width][height]; int n2 = N/2; for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) { dummy[i][j] = p[i][j]; for (int k = -n2; k <= n2; ++k) for (int l = -n2; l <= n2; ++l) { if (!(i+k < 0 || i+k >= width || j+l < 0 || j+l >= height) && p[i+k][j+l] == num) { dummy[i][j] = num; break; } } } for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) p[i][j] = dummy[i][j]; cout << "done!" << endl; } //*************************************************************************** void GrayImage::ErosionNxN_Binary (int N, int num) // odd N { // num -> object with label "num" cout << " Applying " << N << "x" << N << " Erosion operator to component " << num << "..."; int dummy[width][height]; int n2 = N/2; for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) { dummy[i][j] = p[i][j]; for (int k = -n2; k <= n2; ++k) for (int l = -n2; l <= n2; ++l) { if (!(i+k < 0 || i+k >= width || j+l < 0 || j+l >= height) && p[i+k][j+l] != num) { dummy[i][j] = 0; break; } } } for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) p[i][j] = dummy[i][j]; cout << "done!" << endl; } //*************************************************************************** void GrayImage::OpeningNxN_Binary (int N, int num) // odd N, num => component number { cout << "Applying " << N << "x" << N << " OPENING operator to component " << num << "..." << endl; ErosionNxN_Binary ( N, num ); DilationNxN_Binary ( N, num ); cout << "done!" << endl; } //*************************************************************************** void GrayImage::ClosingNxN_Binary (int N, int num) // odd N, num => component number { cout << "Applying " << N << "x" << N << " CLOSING operator to component " << num << "..." << endl; DilationNxN_Binary ( N, num ); ErosionNxN_Binary ( N, num ); cout << "done!" << endl; } //*************************************************************************** void GrayImage::OpeningNxN_Binary (int N) // odd N { GrayImage final(width, height, numLevels); GrayImage original; original = *this; for (int i = 1; i <= numComponents; i++) { GrayImage dummy; dummy = original; dummy.OpeningNxN_Binary ( N, i ); final = final + dummy; } *this = final; } //*************************************************************************** void GrayImage::ClosingNxN_Binary (int N) // odd N { GrayImage final(width, height, numLevels); GrayImage original; original = *this; for (int i = 1; i <= numComponents; i++) { GrayImage dummy; dummy = original; dummy.ClosingNxN_Binary ( N, i ); final = final + dummy; } *this = final; } //*************************************************************************** void GrayImage::ErosionNxN_Binary (int N) // odd N { GrayImage final(width, height, numLevels); GrayImage original; original = *this; for (int i = 1; i <= numComponents; i++) { GrayImage dummy; dummy = original; dummy.ErosionNxN_Binary ( N, i ); final = final + dummy; } *this = final; } //*************************************************************************** void GrayImage::DilationNxN_Binary (int N) // odd N { for (int i = 1; i <= numComponents; i++) DilationNxN_Binary ( N, i ); } //*************************************************************************** void GrayImage::ErosionNxN (int N) // odd N { cout << " Applying " << N << "x" << N << " Local Minimum (Erosion) filter..."; int dummy[width][height]; int n2 = N/2; for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) { dummy[i][j] = INT_MAX; for (int k = -n2; k <= n2; ++k) for (int l = -n2; l <= n2; ++l) if (!(i+k < 0 || i+k >= width || j+l < 0 || j+l >= height) && p[i+k][j+l] < dummy[i][j]) dummy[i][j] = p[i+k][j+l]; } for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) p[i][j] = dummy[i][j]; cout << "done!" << endl; } //*************************************************************************** void GrayImage::DilationNxN (int N) // odd N { cout << " Applying " << N << "x" << N << " Local Maximum (Dilation) filter..."; int dummy[width][height]; int n2 = N/2; for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) { dummy[i][j] = INT_MIN; for (int k = -n2; k <= n2; ++k) for (int l = -n2; l <= n2; ++l) if (!(i+k < 0 || i+k >= width || j+l < 0 || j+l >= height) && p[i+k][j+l] > dummy[i][j]) dummy[i][j] = p[i+k][j+l]; } for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) p[i][j] = dummy[i][j]; cout << "done!" << endl; } //*************************************************************************** void GrayImage::OpeningNxN (int N) // odd N { cout << "Applying " << N << "x" << N << " OPENING operator..." << endl; ErosionNxN( N ); DilationNxN( N ); cout << "done!" << endl; } //*************************************************************************** void GrayImage::ClosingNxN (int N) // odd N { cout << "Applying " << N << "x" << N << " CLOSING operator..." << endl; DilationNxN( N ); ErosionNxN( N ); cout << "done!" << endl; } //*************************************************************************** void GrayImage::Skeletonization ( ) // Medial Axis Thinning { cout << "Applying Skeletonization to binary image..."; int **dummy, **dummyk, **dummyk1, **ptrk, **ptrk1; dummy = new int *[width]; dummyk = new int *[width]; dummyk1 = new int *[width]; for (int i = 0; i < width; i++) { dummy[i] = new int [height]; dummyk[i] = new int [height]; dummyk1[i] = new int [height]; } ptrk = dummyk; ptrk1 = dummyk1; for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) if (p[i][j] == 0) dummy[i][j] = ptrk[i][j] = ptrk1[i][j] = 0; else dummy[i][j] = ptrk[i][j] = ptrk1[i][j] = 1; int k = 1; int flag; do { flag = 1; ptrk = dummyk; ptrk1 = dummyk1; for (int i = 1; i < width-1; ++i) for (int j = 1; j < height-1; ++j) if (ptrk1[i][j] == k) { int min = ptrk1[i-1][j]; if (min > ptrk1[i+1][j]) min = ptrk1[i+1][j]; if (min > ptrk1[i][j+1]) min = ptrk1[i][j+1]; if (min > ptrk1[i][j-1]) min = ptrk1[i][j-1]; if (min == k) { ptrk[i][j] = min + 1; flag = 0; } } k++; /* Next Iteration */ ptrk = dummyk; ptrk1 = dummyk1; for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) if (ptrk[i][j] == k) ptrk1[i][j] = k; } while (flag == 0); ptrk = dummyk; for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) p[i][j] = ptrk[i][j]; for (int i = 1; i < width-1; ++i) for (int j = 1; j < height-1; ++j) { unsigned char val = p[i][j]; if (val) { unsigned char max = p[i-1][j]; if (max < p[i+1][j]) max = p[i+1][j]; if (max < p[i][j+1]) max = p[i][j+1]; if (max < p[i][j-1]) max = p[i][j-1]; if (val >= max) dummy[i][j] = 255; else dummy[i][j] = 0; } } for (int i = 0; i < width; ++i) dummy[i][0] = dummy[i][height-1] = 0; for (int j = 0; j < height; ++j) dummy[0][j] = dummy[width-1][j] = 0; for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) p[i][j] = dummy[i][j]; cout << "done!" << endl; for (int i = 0; i < width; i++) { delete dummy[i]; delete dummyk[i]; delete dummyk1[i]; } delete dummy; delete dummyk; delete dummyk1; } //*************************************************************************** void GrayImage::MeanFilterNxN (int N) // odd N { cout << "Applying " << N << "x" << N << " mean filter..."; int dummy[width][height]; int n2 = N/2; for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) { dummy[i][j] = 0; int m = 0; for (int k = -n2; k <= n2; ++k) for (int l = -n2; l <= n2; ++l) if (!(i+k < 0 || i+k >= width || j+l < 0 || j+l >= height)) { dummy[i][j] += p[i+k][j+l]; ++m; } dummy[i][j] /= m; } for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) p[i][j] = dummy[i][j]; cout << "done!" << endl; } //*************************************************************************** void GrayImage::MedianFilterNxN (int N) // odd N { cout << "Applying " << N << "x" << N << " median filter..."; int dummy[width][height]; int n2 = N/2; for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) { int list[N*N]; int m = 0; for (int k = -n2; k <= n2; ++k) for (int l = -n2; l <= n2; ++l) if (!(i+k < 0 || i+k >= width || j+l < 0 || j+l >= height)) list[m++] = p[i+k][j+l]; qsort(list,m,sizeof(int),compareIntegers); if (m % 2) dummy[i][j] = (list[m/2]+list[m/2-1])/2; else dummy[i][j] = list[m/2]; } for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) p[i][j] = dummy[i][j]; cout << "done!" << endl; } //*************************************************************************** void GrayImage::kNearestNeighboringFilterNxN (int N) // odd N { kNearestNeighboringFilterNxN(N, N*N/2+1); } //*************************************************************************** void GrayImage::kNearestNeighboringFilterNxN (int N, int k2) // odd N { cout << "Applying " << N << "x" << N << " k-Nearest (k = " << k2 << ") Neigboring filter..."; cout.flush(); int dummy[width][height]; int n2 = N/2; for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) { int list[N*N]; int m = 0; for (int k = -n2; k <= n2; ++k) for (int l = -n2; l <= n2; ++l) if (!(i+k < 0 || i+k >= width || j+l < 0 || j+l >= height)) list[m++] = p[i+k][j+l]; dummy[i][j] = findknearest(list, m, k2); } for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) p[i][j] = (unsigned char) dummy[i][j]; cout << "done!" << endl; } //*************************************************************************** static int findknearest(int list[], int m, int k) { int center = list[m/2]; // odd N only mydiff diff[m]; for (int i = 0; i < m; ++i) { diff[i].id = i; diff[i].value = abs(list[i]-center); } qsort(diff,m,sizeof(mydiff),compareIntegers2); int value = 0; if (k > m) k = m; for (int i = 0; i < k; ++i) { value += list[diff[i].id]; } value /= k; return value; } //*************************************************************************** // A NxN Gaussian filter from // Machine Vision text, pages 132-137 //*************************************************************************** void GrayImage::GaussianFilterNxN (int N) // odd N { cout << "Applying " << N << "x" << N << " Gaussian filter..."; cout.flush(); double temp[N][N]; int mask[N][N]; double out[width][height]; int i, j, k, l; int N2 = N/2; int normfactor = 0; double sd = 1.0; for (i = -N2; i <= N2; i++) for (j = -N2; j <= N2; j++) { temp[i+N2][j+N2] = exp(-1.0*((i*i+j*j)/(2.0*(sd*sd)))); mask[i+N2][j+N2] = (int) rint(1.0/temp[0][0]*temp[i+N2][j+N2]); normfactor += mask[i+N2][j+N2]; } int printmask = 1; if (printmask) { printf("\n"); for (i = -N2; i <= N2; i++) { for (j = -N2; j <= N2; j++) printf("%g ",mask[i+N2][j+N2]*1.0/normfactor); printf("\n"); } printf("normfactor = %d\n",normfactor); } for (i = 0; i < width; i++) for (j = 0; j < height; j++) out[i][j] = 0.0; for (i = N2; i < width - N2; i++) for (j = N2; j < height - N2; j++) for (k = -N2; k <= N2; k++) for (l = -N2; l <= N2; l++) out[i][j] += p[i+k][j+l]*mask[k+N2][l+N2] *1.0/normfactor; for (i = N2; i < width - N2; i++) for (j = N2; j < height - N2; j++) p[i][j] = (unsigned char) out[i][j]; cout << "done!" << endl; } //***************************************************************************