Image processing – Prewitt filter in C

I

Edge detection is the process of identify the presence and location of edges by sharp discontinuities of image. Edge detection plays an important role in image processing and helps in solving many complex problems. One useful and easy to implement algorithm is the Prewitt filter. As compared to Sobel, the Prewitt masks are simpler to implement but are very sensitive to noise. Mathematically, the operator uses two 3×3 kernels which are convolved with the original image to calculate approximations of the derivatives – one for horizontal changes, and one for vertical.

Extra Information:

There are four types of edges which are described below:

  1. Step Edge – The intensity of image abruptly varies from one value to one side of the breakage to a different value on other side.
  2. Ramp Edge – When the intensity change is not spontaneous and appears a limited distance then step edges are changed to ramp edges.
  3. Ridge/Line Edge – The intensity of image suddenly changes values and then returns to the starting point within short distance.
  4. Roof Edge – When intensity change is not spontaneous and appears over a finite distance usually generated by connectivity of surfaces then line edges becomes roof edges.

Below is the source code in C Language of the prewitt filter as well as the bitmap library to load and use images:

#ifndef _PREWITT_H
	#define _PREWITT_H

		#include <math.h>
		#include <float.h>
		#include <stdio.h>
		#include <stdint.h>
		#include <stdlib.h>
		#include "bitmap.h"

	void Prewitt_Filter(bitmap_t *, int, int);

#endif
#include "prewitt.h"

	void Prewitt_Filter(bitmap_t * bitmap, int swidth,int ewidth)
	{
		bmp_pixel_t ** result;	
		float accum1 = 0, accum2 = 0;
		int row1 = 0, col1 = 0, row, col, i, j;
	
		float kGx[3][3] = { { -1.0f, 0, 1.0f },{ -1.0f, 0, 1.0f },{ -1.0f, 0, 1.0f } };
		float kGy[3][3] = { { -1.0f, -1.0f, -1.0f },{ 0, 0, 0 },{ 1.0f, 1.0f, 1.0f } };
				
		if( (result = (bmp_pixel_t **) malloc((bitmap->dheader.height)*sizeof(bmp_pixel_t *))) == NULL)	
			return;
		
		for (i = 0; i < (bitmap->dheader.height); i++)		
			if( (result[i] = (bmp_pixel_t*) malloc((ewidth-swidth)*sizeof(bmp_pixel_t))) == NULL)	
				return;
		
		for (row = 0; row < bitmap->dheader.height; row++)		
			for (col = swidth; col < ewidth; col++) 
			{
				accum1 = 0;		
				accum2 = 0;
				
				for (i = -1; i <= 1; i++)		
					for (j = -1; j <= 1; j++) 
					{
						row1 = row + i >= 0 ? row + i : 0;	
						col1 = col + j >= swidth  ? col + j : 0;		
						row1 = row + i >= bitmap->dheader.height ? bitmap->dheader.height - 1 : row1;		
						col1 = col + j >= ewidth  ? ewidth - 1  : col1;			
						accum1 += bitmap->pixels[row1][col1].value * kGy[1 + i][1 + j];	
						accum2 += bitmap->pixels[row1][col1].value * kGx[1 + i][1 + j];
						
					}					
				result[row-0][col-swidth].value = (int) sqrt(pow(accum1, 2) + pow(accum2, 2));
			}
			
		for (row = 0; row < bitmap->dheader.height; row++) 			
			for (col = swidth; col < ewidth; col++) 				
				bitmap->pixels[row][col].value=result[row-0][col-swidth].value;
			
		for (i = 0; i < bitmap->dheader.height; i++)			
			free(result[i]);
			
		free(result);
	}

 

#ifndef _BITMAP_H
	#define _BITMAP_H
		
		#include <math.h>
		#include <float.h>
		#include <stdio.h>
		#include <stdint.h>		
		#include <stdlib.h>
		#include <string.h>
		#include <assert.h>
		#include <stdbool.h>
		
		typedef struct bmp_header_t
		{
			uint32_t filesize;			
			uint16_t undefined0;			
			uint16_t undefined1;			
			uint32_t dataoffset;
		}
		bmp_header_t;

		typedef struct dib_header_t
		{
			uint32_t dipsize;			
			int32_t  width;			
			int32_t  height;			
			uint16_t nplanes;			
			uint16_t depth;		
			uint32_t compress_type;			
			uint32_t bmp_bytesz;			
			int32_t  hres;			
			int32_t  vres;			
			uint32_t ncolors;			
			uint32_t nimpcolors;
		}
		dib_header_t;

		typedef struct bmp_pixel_t
		{
			unsigned int value;
		}
		bmp_pixel_t;

		typedef struct bitmap_t
		{
			struct bmp_header_t  fheader;			
			struct dib_header_t  dheader;			
			struct bmp_pixel_t ** pixels;
		}
		bitmap_t;

		struct bitmap_t * image_load(char *);		
		int image_save(char *, struct bitmap_t *);
		
#endif

 

#include "bitmap.h"

	struct bitmap_t * image_load(char * filename)
	{
		FILE * filePtr;		
		bmp_pixel_t ** pixels;		
		size_t pad=0,i,j;		
		bitmap_t * bitmap;		
		char magic[2];	
		int sum = 0,q;
		uint8_t b;
		
		if ( (filePtr = fopen(filename, "rb")) == NULL ) 			
			return NULL;

		if ( fread(&magic, sizeof(magic), 1, filePtr) != 1 )
		{
			fclose(filePtr);			
			return NULL;
		}		
		if ( *((uint16_t*) magic) != 0x4D42 )
		{
			fclose(filePtr);			
			return NULL;
		}
		
		if( (bitmap = (bitmap_t *) malloc(sizeof(bitmap_t))) == NULL )		
			return NULL;

		if ( fread(&(bitmap->fheader), sizeof(bmp_header_t),1, filePtr) != 1 )
		{
			fclose(filePtr);			
			return NULL;
		}	
		
		if ( fread(&(bitmap->dheader), sizeof(dib_header_t),1, filePtr) != 1 )
		{
			fclose(filePtr);			
			return NULL;
		}
		
		if ( bitmap->dheader.compress_type != 0 ) 
		{
			fclose(filePtr);			
			return NULL;
		}
		
		if ( fseek(filePtr, bitmap->fheader.dataoffset, SEEK_SET) )
		{
			fclose(filePtr);			
			return NULL;
		}
		
		if ( bitmap->dheader.depth != 24 ) 
		{
			fclose(filePtr);			
			return NULL;
		}
		
		if( (pixels = (bmp_pixel_t**) malloc(bitmap->dheader.height*sizeof(bmp_pixel_t*))) == NULL )
		{
			fclose(filePtr);				
			return NULL;
		}
			
		for (i = 0; i < bitmap->dheader.height; i++)		
			if( (pixels[i] = (bmp_pixel_t*) malloc(bitmap->dheader.width*sizeof(bmp_pixel_t))) == NULL )
			{
				fclose(filePtr);					
				return NULL;
			}
		
		if ( ((bitmap->dheader.width*bitmap->dheader.depth / 8) % 4) != 0 )		
			pad = 4 - ((bitmap->dheader.width*bitmap->dheader.depth / 8) % 4);  

		for (i = 0; i < bitmap->dheader.height; i++) 
		{
			for (j = 0; j < bitmap->dheader.width; j++) 
			{
				sum = 0;			
				for (q = 0; q < 3; q++)
				{
					if ( fread(&b, sizeof(uint8_t), 1, filePtr) != 1 ) 
					{
						fclose(filePtr);		
						break;
					}					
					sum += b;				
				}				
				pixels[bitmap->dheader.height-(i+1)][bitmap->dheader.width-(j+1)].value = sum / 3;
			}		
			fseek(filePtr, pad, SEEK_CUR);
		}
		
		bitmap->pixels = pixels;		
		fclose(filePtr);		
		return bitmap;
	}
	
	
	int image_save(char * filename, struct bitmap_t * bitmap)
	{
		char c = 0;		
		size_t pad = 0,i,j,q;		
		char magic[] = {0x42,0x4d};		
		FILE* filePtr;
		
		if ( (filePtr = fopen(filename, "wb")) == NULL ) 			
			return -1;

		if ( fwrite(&magic, sizeof(magic), 1, filePtr) != 1 ) 				
		{
			fclose(filePtr);			
			return -1;
		}	
		
		if ( fwrite(&bitmap->fheader, sizeof(bmp_header_t), 1, filePtr) != 1 )	
		{
			fclose(filePtr);				
			return -1;
		}
		
		if ( fwrite(&bitmap->dheader, sizeof(dib_header_t), 1, filePtr) != 1 )	
		{
			fclose(filePtr);			
			return -1;
		}
		
		if ( ((bitmap->dheader.width*bitmap->dheader.depth / 8) % 4) != 0 )		
			pad = 4 - ((bitmap->dheader.width*bitmap->dheader.depth / 8) % 4);	

		for (i = 0; i < bitmap->dheader.height; i++) 
		{
			for (j = 0; j < bitmap->dheader.width; j++) 
			{
				c = (unsigned char) bitmap->pixels[bitmap->dheader.height - (i + 1)][bitmap->dheader.width - (j + 1)].value;
				
				for (q = 0; q < 3; q++)		
					if ( fwrite(&c, sizeof(char), 1, filePtr) != 1 ) 			
						{fclose(filePtr);	return 0;}				
			}
			
			c = 0;	
			for (j = 0; j<pad; j++)			
				if ( fwrite(&c, sizeof(char), 1, filePtr) != 1 ) 
				{
					fclose(filePtr);					
					return 0;
				}
		}
		
		fclose(filePtr);	
		return 0;
	}

 

Please refer to: https://gitlab.com/iikem/threads-benchmark-prewitt for a complete example.

Disclaimer: The present content may not be used for training artificial intelligence or machine learning algorithms. All other uses, including search, entertainment, and commercial use, are permitted.

Categories

Tags