void triangularSmooth(unsigned char *grayImage, unsigned char *smoothImage, const int width, const int height, const float *filter, NSTimer &timer) { NSTimer kernelTime = NSTimer("kernelTime", false, false); kernelTime.start(); // Kernel for ( int y = 0; y < height; y++ ) { for ( int x = 0; x < width; x++ ) { unsigned int filterItem = 0; float filterSum = 0.0f; float smoothPix = 0.0f; for ( int fy = y - 2; fy < y + 3; fy++ ) { for ( int fx = x - 2; fx < x + 3; fx++ ) { if ( ((fy < 0) || (fy >= height)) || ((fx < 0) || (fx >= width)) ) { filterItem++; continue; } smoothPix += grayImage[(fy * width) + fx] * filter[filterItem]; filterSum += filter[filterItem]; filterItem++; } } smoothPix /= filterSum; smoothImage[(y * width) + x] = static_cast< unsigned char >(smoothPix); } } // /Kernel kernelTime.stop(); cout << fixed << setprecision(6); cout << "triangularSmooth (kernel): \t" << kernelTime.getElapsed() << " seconds." << endl; }
void contrast1D(unsigned char *grayImage, const int width, const int height, unsigned int *histogram, const unsigned int HISTOGRAM_SIZE, const unsigned int CONTRAST_THRESHOLD, NSTimer &timer) { unsigned int i = 0; NSTimer kernelTime = NSTimer("kernelTime", false, false); while ( (i < HISTOGRAM_SIZE) && (histogram[i] < CONTRAST_THRESHOLD) ) { i++; } unsigned int min = i; i = HISTOGRAM_SIZE - 1; while ( (i > min) && (histogram[i] < CONTRAST_THRESHOLD) ) { i--; } unsigned int max = i; float diff = max - min; kernelTime.start(); // Kernel for ( int y = 0; y < height; y++ ) { for (int x = 0; x < width; x++ ) { unsigned char pixel = grayImage[(y * width) + x]; if ( pixel < min ) { pixel = 0; } else if ( pixel > max ) { pixel = 255; } else { pixel = static_cast< unsigned char >(255.0f * (pixel - min) / diff); } grayImage[(y * width) + x] = pixel; } } // /Kernel kernelTime.stop(); cout << fixed << setprecision(6); cout << "contrast1D (kernel): \t\t" << kernelTime.getElapsed() << " seconds." << endl; }
void histogram1D(unsigned char *grayImage, unsigned char *histogramImage, const int width, const int height, unsigned int *histogram, const unsigned int HISTOGRAM_SIZE, const unsigned int BAR_WIDTH, NSTimer &timer) { unsigned int max = 0; NSTimer kernelTime = NSTimer("kernelTime", false, false); memset(reinterpret_cast< void * >(histogram), 0, HISTOGRAM_SIZE * sizeof(unsigned int)); kernelTime.start(); // Kernel for ( int y = 0; y < height; y++ ) { for ( int x = 0; x < width; x++ ) { histogram[static_cast< unsigned int >(grayImage[(y * width) + x])] += 1; } } // /Kernel kernelTime.stop(); for ( unsigned int i = 0; i < HISTOGRAM_SIZE; i++ ) { if ( histogram[i] > max ) { max = histogram[i]; } } for ( int x = 0; x < HISTOGRAM_SIZE * BAR_WIDTH; x += BAR_WIDTH ) { unsigned int value = HISTOGRAM_SIZE - ((histogram[x / BAR_WIDTH] * HISTOGRAM_SIZE) / max); for ( unsigned int y = 0; y < value; y++ ) { for ( unsigned int i = 0; i < BAR_WIDTH; i++ ) { histogramImage[(y * HISTOGRAM_SIZE * BAR_WIDTH) + x + i] = 0; } } for ( unsigned int y = value; y < HISTOGRAM_SIZE; y++ ) { for ( unsigned int i = 0; i < BAR_WIDTH; i++ ) { histogramImage[(y * HISTOGRAM_SIZE * BAR_WIDTH) + x + i] = 255; } } } cout << fixed << setprecision(6); cout << "histogram1D (kernel): \t\t" << kernelTime.getElapsed() << " seconds." << endl; }
void rgb2gray(unsigned char *inputImage, unsigned char *grayImage, const int width, const int height, NSTimer &timer) { NSTimer kernelTime = NSTimer("kernelTime", false, false); kernelTime.start(); // Kernel for ( int y = 0; y < height; y++ ) { for ( int x = 0; x < width; x++ ) { float grayPix = 0.0f; float r = static_cast< float >(inputImage[(y * width) + x]); float g = static_cast< float >(inputImage[(width * height) + (y * width) + x]); float b = static_cast< float >(inputImage[(2 * width * height) + (y * width) + x]); grayPix = (0.3f * r) + (0.59f * g) + (0.11f * b); grayImage[(y * width) + x] = static_cast< unsigned char >(grayPix); } } // /Kernel kernelTime.stop(); cout << fixed << setprecision(6); cout << "rgb2gray (kernel): \t\t" << kernelTime.getElapsed() << " seconds." << endl; }
int main(int argc, char *argv[]) { NSTimer total = NSTimer("total", false, false); if ( argc != 2 ) { cerr << "Usage: " << argv[0] << " <filename>" << endl; return 1; } // Load the input image CImg< unsigned char > inputImage = CImg< unsigned char >(argv[1]); if ( displayImages ) { inputImage.display("Input Image"); } if ( inputImage.spectrum() != 3 ) { cerr << "The input must be a color image." << endl; return 1; } // Image is loaded, start timing total.start(); // Convert the input image to grayscale CImg< unsigned char > grayImage = CImg< unsigned char >(inputImage.width(), inputImage.height(), 1, 1); rgb2gray(inputImage.data(), grayImage.data(), inputImage.width(), inputImage.height(), total); total.stop(); if ( displayImages ) { grayImage.display("Grayscale Image"); } if ( saveAllImages ) { grayImage.save("./grayscale.bmp"); } total.start(); // Compute 1D histogram CImg< unsigned char > histogramImage = CImg< unsigned char >(BAR_WIDTH * HISTOGRAM_SIZE, HISTOGRAM_SIZE, 1, 1); unsigned int *histogram = new unsigned int [HISTOGRAM_SIZE]; histogram1D(grayImage.data(), histogramImage.data(), grayImage.width(), grayImage.height(), histogram, HISTOGRAM_SIZE, BAR_WIDTH, total); total.stop(); if ( displayImages ) { histogramImage.display("Histogram"); } if ( saveAllImages ) { histogramImage.save("./histogram.bmp"); } total.start(); // Contrast enhancement contrast1D(grayImage.data(), grayImage.width(), grayImage.height(), histogram, HISTOGRAM_SIZE, CONTRAST_THRESHOLD, total); total.stop(); if ( displayImages ) { grayImage.display("Contrast Enhanced Image"); } if ( saveAllImages ) { grayImage.save("./contrast.bmp"); } total.start(); delete [] histogram; // Triangular smooth (convolution) CImg< unsigned char > smoothImage = CImg< unsigned char >(grayImage.width(), grayImage.height(), 1, 1); triangularSmooth(grayImage.data(), smoothImage.data(), grayImage.width(), grayImage.height(), filter, total); // Job done, stop timing total.stop(); if ( displayImages ) { smoothImage.display("Smooth Image"); } smoothImage.save("./smooth.bmp"); // Wrap up cout << fixed << setprecision(6) << endl; cout << "Execution time: \t\t" << total.getElapsed() << " seconds." << endl << endl; return 0; }