Last active
August 29, 2015 14:02
-
-
Save ahmpro/1ae26501e7cde632e5d0 to your computer and use it in GitHub Desktop.
Sobel filter with threads - lab 5 on "Operating Systems" in MAI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
input images: | |
https://www.dropbox.com/s/hs5wxfz6pdk1387/nice.pgm | |
and | |
https://www.dropbox.com/s/dzi8mcadrxn5f2v/opasno.pgm |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
all: | |
gcc -Wall -lm -lpthread -std=gnu99 sobel.c -o sobel | |
clean: | |
rm sobel | |
rm edgemap_sobel.pgm | |
rm work.txt | |
rm table.txt | |
rm letsrock.pgm | |
check: | |
cppcheck --enable=all --inconclusive --std=posix sobel.c | |
/home/l1s/linux-source/scripts/checkpatch.pl -f sobel.c | |
well: | |
make clean -i | |
cp nice.pgm letsrock.pgm | |
clear | |
make | |
(for i in {1..20}; do (time ./sobel letsrock.pgm $$i;) 2>> work.txt; done;) | |
(cat work.txt | grep real | cut -b 8-12 >> table.txt) | |
rm work.txt | |
opasno: | |
make clean -i | |
cp opasno.pgm letsrock.pgm | |
clear | |
make | |
(for i in {1..20}; do (time ./sobel letsrock.pgm $$i;) 2>> work.txt; done;) | |
(cat work.txt | grep real | cut -b 8-12 >> table.txt) | |
rm work.txt |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/****************************************************************************/ | |
/* Edge Detection Program */ | |
/* ECE 532 : Digital Image Analysis */ | |
/* | |
Input: PGM file | |
Output:PGM file | |
Author: Nikhil Shirahatti | |
Date: 09/13/2003 | |
Edited by: L1S and ahmpro | |
Date: 15 May 2014 | |
*****************************************************************************/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <pthread.h> | |
#include <math.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#define NUMTHREADS 20 | |
extern int read_pgm_hdr(FILE *, int *, int *); | |
extern void **matrix(int, int, int, int, int); | |
extern void error(const char *); | |
int skipNMS=0; | |
pthread_mutex_t lock; | |
struct SobelStruct { | |
unsigned char **xc; | |
unsigned char **edgemap; | |
int nrows, ncols; | |
int s_row, e_row; | |
int s_col, e_col; | |
int thresh; | |
}; | |
int skipcomment(FILE *fp) | |
{ | |
int i; | |
if((i = getc(fp)) == '#') | |
while((i = getc(fp)) != '\n' && i != EOF); | |
return(ungetc(i, fp)); | |
} | |
int read_pgm_hdr(FILE *fp, int *nrows, int *ncols) | |
{ | |
char filetype[3], comment[512]; | |
int maxval; | |
if(skipcomment(fp) == EOF | |
|| fscanf(fp, "%2s", filetype) != 1 | |
|| strcmp(filetype, "P5") | |
|| skipcomment(fp) == EOF | |
|| fscanf(fp, "%s", comment) != 1 | |
|| fscanf(fp, "%s", comment) != 1 | |
|| fscanf(fp, "%s", comment) != 1 | |
|| fscanf(fp, "%s", comment) != 1 | |
|| fscanf(fp, "%s", comment) != 1 | |
|| fscanf(fp, "%s", comment) != 1 | |
|| fscanf(fp, "%s", comment) != 1 | |
|| fscanf(fp, "%d", ncols) != 1 | |
|| skipcomment(fp) == EOF | |
|| fscanf(fp, "%d", nrows) != 1 | |
|| skipcomment(fp) == EOF | |
|| fscanf(fp, "%d%*c", &maxval) != 1 | |
|| maxval > 255) | |
return(-1); | |
else return(0); | |
} | |
void error(const char *msg) | |
{ | |
fprintf(stderr, "%s\n", msg); | |
exit(1); | |
} | |
void **matrix(int nrows, int ncols, int first_row_coord, int first_col_coord, int element_size) | |
{ | |
void **p; | |
int alignment; | |
long i; | |
if(nrows < 1 || ncols < 1) return(NULL); | |
i = nrows*sizeof(void *); | |
alignment = i % sizeof(long double); | |
if(alignment != 0) alignment = sizeof(long double) - alignment; | |
i += nrows*ncols*element_size+alignment; | |
if((p = (void **)malloc((size_t)i)) != NULL) { | |
p[0] = (char *)(p+nrows)+alignment-first_col_coord*element_size; | |
for(i = 1; i < nrows; i++) | |
p[i] = (char *)(p[i-1])+ncols*element_size; | |
p -= first_row_coord; | |
} | |
return(p); | |
} | |
void* sobel(void *arg) | |
{ | |
struct SobelStruct *params = (struct SobelStruct*) arg; | |
unsigned char **xc = params->xc; | |
unsigned char **edgemap = params->edgemap; | |
int s_row = params->s_row; | |
int e_row = params->e_row; | |
int s_col = params->s_col; | |
int e_col = params->e_col; | |
int thresh = params->thresh; | |
float **row, **col,**theta,**y; | |
int i,j,edgepoints=0; | |
int nrows = e_row, ncols = e_col; | |
row = (float **)matrix(nrows, ncols, 0, 0, sizeof(float)); | |
col = (float **)matrix(nrows, ncols, 0, 0, sizeof(float)); | |
theta = (float **)matrix(nrows+2, ncols+2, -1, -1, sizeof(float)); | |
y = (float **)matrix(nrows+2, ncols+2, -1, -1, sizeof(float)); | |
if( row == NULL || col == NULL || theta == NULL || y == NULL || edgemap == NULL) | |
error(" Allocation error of matrices in Sobel's sub-function\n"); | |
//printf("Run thread on %d:%d\n", s_row, e_row); | |
if (s_row == 0) { | |
s_row = 1; | |
} | |
if (e_row == params->nrows) { | |
e_row = e_row - 1; | |
} | |
for(i = s_row; i < e_row; i++) { | |
for(j = s_col+1; j < e_col-1; j++) { | |
row[i][j] = (float)(xc[i+1][j-1] + 2*xc[i+1][j]+xc[i+1][j-1] - xc[i-1][j-1] - 2*xc[i-1][j] -xc[i-1][j+1])/8; | |
col[i][j]= (float)(xc[i-1][j-1] + 2*xc[i][j-1]+xc[i+1][j-1] - xc[i-1][j+1] - 2*xc[i][j+1] - xc[i+1][j-1])/8; | |
y[i][j] = row[i][j]*row[i][j]+ col[i][j]*col[i][j]; | |
theta[i][j]= atan2(col[i][j],row[i][j]); | |
} | |
} | |
for(i = s_row; i < e_row; i++) { | |
for(j = s_col; j < e_col; j++) { | |
if(y[i][j] >= thresh*thresh) { | |
edgemap[i][j] = 255; | |
edgepoints++; | |
} else { | |
edgemap[i][j] =0; | |
} | |
} | |
} | |
//printf(" Number of Edgepoints using simple thresholding is %d\n",edgepoints); | |
return NULL; | |
} | |
void read_pgm(unsigned char **pgm_matrix, FILE *pgm_file, int nrows, int ncols) { | |
int i, j; | |
for (i = 0; i < nrows; ++i) { | |
for (j = 0; j < ncols; ++j) { | |
pgm_matrix[i][j] = fgetc(pgm_file); | |
} | |
} | |
} | |
int main(int argc, char **argv) | |
{ | |
FILE *fpx, *fpy; | |
int nrows, ncols, i, curthreads = NUMTHREADS; | |
if (argc != 3) { | |
error("invalid args"); | |
} | |
curthreads = atoi(argv[2]); | |
if (curthreads < 1 || curthreads > NUMTHREADS) { | |
error("num threads should be in 1;"+NUMTHREADS); | |
} | |
printf("Using %d threads\n", curthreads); | |
if((fpx = fopen(argv[1], "r"))== NULL) { | |
printf("%s\n", argv[1]); | |
error("can't open file"); | |
} | |
if(read_pgm_hdr(fpx, &nrows, &ncols) < 0) | |
error("not a PGM image or bpp > 8"); | |
unsigned char **xc = (unsigned char **) matrix(nrows,ncols,0,0,sizeof(char)); | |
unsigned char **edgemap = (unsigned char **) matrix(nrows,ncols,0,0,sizeof(char)); | |
read_pgm(xc, fpx, nrows, ncols); | |
if((fpy =fopen("edgemap_sobel.pgm","w"))== 0) | |
error(" Error writing file\n"); | |
printf("image %dx%d\n", nrows, ncols); | |
struct SobelStruct sobel_threads[NUMTHREADS]; | |
pthread_t thread[NUMTHREADS]; | |
int chunk = nrows/curthreads; | |
int pointer = 0; | |
for(i = 0; i<curthreads; i++) { | |
sobel_threads[i].xc = xc; | |
sobel_threads[i].edgemap = edgemap; | |
sobel_threads[i].nrows = nrows; | |
sobel_threads[i].ncols = ncols; | |
sobel_threads[i].s_row = pointer; | |
sobel_threads[i].e_row = pointer+chunk; | |
if (sobel_threads[i].e_row >= nrows) { | |
sobel_threads[i].e_row = nrows; | |
} | |
sobel_threads[i].s_col = 0; | |
sobel_threads[i].e_col = ncols; | |
sobel_threads[i].thresh = 3; | |
pointer += chunk; | |
} | |
pthread_mutex_init(&lock, NULL); | |
for (i=0; i<curthreads; i++) { | |
pthread_create(&(thread[i]), NULL, sobel, &(sobel_threads[i])); | |
} | |
for (i=0; i<curthreads; i++) { | |
pthread_join(thread[i], NULL); | |
} | |
fprintf(fpy, "P5\n%d %d\n255\n", ncols, nrows); | |
for(i = 0; i < nrows; i++) { | |
if(fwrite(&edgemap[i][0], sizeof(char), ncols, fpy) != ncols) | |
error("can't write the image"); | |
} | |
fclose(fpy); | |
fclose(fpx); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment