Skip to content

Instantly share code, notes, and snippets.

@ahmpro
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahmpro/1ae26501e7cde632e5d0 to your computer and use it in GitHub Desktop.
Save ahmpro/1ae26501e7cde632e5d0 to your computer and use it in GitHub Desktop.
Sobel filter with threads - lab 5 on "Operating Systems" in MAI
input images:
https://www.dropbox.com/s/hs5wxfz6pdk1387/nice.pgm
and
https://www.dropbox.com/s/dzi8mcadrxn5f2v/opasno.pgm
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
/****************************************************************************/
/* 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