Skip to content

Commit 297cf4c

Browse files
author
Ryan Lewis
committed
Add cs652
- Added sobel operator assignment
1 parent a83410e commit 297cf4c

File tree

2 files changed

+281
-0
lines changed

2 files changed

+281
-0
lines changed

cs652/sobel/Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CC = gcc
2+
3+
all: convolve
4+
5+
convolve:
6+
$(CC) convolve.c -o convolve -lm
7+
8+
clean:
9+
rm -f convolve g_y.pgm g_x.pgm out.pgm
10+
11+
clean-pgm:
12+
rm -f g_y.pgm g_x.pgm out.pgm

cs652/sobel/convolve.c

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
/*
2+
* Ryan Lewis
3+
* CS652 - Homework 1
4+
*/
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
#include <string.h>
8+
#include <math.h>
9+
10+
/*
11+
* Image struct. Keeps track of image dimensions, maximum value in the image,
12+
* and the matrix of values that make up the image itself.
13+
*/
14+
typedef struct Image {
15+
int row;
16+
int col;
17+
int max_val;
18+
int **img;
19+
} Image;
20+
21+
/*
22+
* Allocate a matrix.
23+
*/
24+
int **alloc_matrix(int row, int col) {
25+
int **ret_matrix = (int **) malloc(sizeof(int *) * row);
26+
int i;
27+
28+
for (i = 0; i < row; i++)
29+
ret_matrix[i] = (int *) malloc(sizeof(int) * col);
30+
31+
return ret_matrix;
32+
}
33+
34+
/*
35+
* Free a matrix.
36+
*/
37+
void **dealloc_matrix(int **matrix, int row) {
38+
int i;
39+
40+
for (i = 0; i < row; i++)
41+
free(matrix[i]);
42+
free(matrix);
43+
}
44+
45+
/*
46+
* Initialize a new matrix with the values of an existing one.
47+
*/
48+
void init_matrix(Image src, Image *dest) {
49+
dest->row = src.row;
50+
dest->col = src.col;
51+
dest->max_val = src.max_val;
52+
dest->img = alloc_matrix(src.row, src.col);
53+
}
54+
55+
/*
56+
* Read a PGM P5 file.
57+
*/
58+
int read_PGM(char *file_name, Image *data) {
59+
int i, j;
60+
FILE * pgm_fp;
61+
char version[3];
62+
63+
if ((pgm_fp = fopen(file_name, "rb")) == NULL) {
64+
fprintf(stderr, "Can not open %s\n", file_name);
65+
return 1;
66+
}
67+
68+
// Make sure the image is of the right version.
69+
fgets(version, sizeof(version), pgm_fp);
70+
if (strcmp(version, "P5")) {
71+
fprintf(stderr, "Invalid PGM format. P5 required.\n");
72+
return 1;
73+
}
74+
75+
fgetc(pgm_fp);
76+
fscanf(pgm_fp, "%d %d", &data->col, &data->row);
77+
fscanf(pgm_fp, "%d", &data->max_val);
78+
fgetc(pgm_fp);
79+
80+
data->img = alloc_matrix(data->row, data->col);
81+
82+
if (data->max_val <= 255) {
83+
for (i = 0; i < data->row; i++) {
84+
for (j = 0; j < data->col; j++) {
85+
data->img[i][j] = fgetc(pgm_fp);
86+
}
87+
}
88+
}
89+
else {
90+
fprintf(stderr, "Error: Max value in source PGM is above 255.");
91+
return 1;
92+
}
93+
94+
fclose(pgm_fp);
95+
96+
return 0;
97+
}
98+
99+
/*
100+
* Write a PGM P5 file.
101+
*/
102+
int write_PGM(char *file_name, Image out) {
103+
FILE * out_fp;
104+
int i, j;
105+
int lo;
106+
107+
if ((out_fp = fopen(file_name, "wb")) == NULL) {
108+
fprintf(stderr, "Could not write output file: %s\n", file_name);
109+
return 1;
110+
}
111+
112+
fprintf(out_fp, "P5\n");
113+
fprintf(out_fp, "%d %d\n", out.col, out.row);
114+
fprintf(out_fp, "%d\n", out.max_val);
115+
116+
if (out.max_val <= 255) {
117+
for (i = 0; i < out.row; i++) {
118+
for (j = 0; j < out.col; j++) {
119+
lo = out.img[i][j] & 0x000000FF;
120+
fputc(lo, out_fp);
121+
}
122+
}
123+
}
124+
else {
125+
fprintf(stderr, "Error: Max value in output PGM is above 255.");
126+
return 1;
127+
}
128+
129+
fclose(out_fp);
130+
131+
return 0;
132+
}
133+
134+
/*
135+
* Convolve. Supports 3x3 filter matrices.
136+
*/
137+
void convolve(int filter[3][3], Image src, Image *result) {
138+
int row, col;
139+
140+
// Loop through the image matrix
141+
for (row = 0; row < src.row; row++) {
142+
for (col = 0; col < src.col; col++) {
143+
int accum = 0;
144+
int i, j;
145+
146+
// Loop through the 3x3 filter matrix
147+
for (i = -1; i <= 1; i++) {
148+
for (j = -1; j <= 1; j++) {
149+
int k;
150+
151+
// If the filter needs to grab a value outside the bounds of the image
152+
// then give it a zero, otherwise give it the actual value.
153+
if (row + i < 0 || row + i > src.row - 1 ||
154+
col + j < 0 || col + j > src.col - 1)
155+
k = 0;
156+
else {
157+
k = src.img[row + i][col + j];
158+
}
159+
160+
accum += k * filter[1 + i][1 + j];
161+
}
162+
}
163+
164+
result->img[row][col] = accum;
165+
}
166+
}
167+
}
168+
169+
/*
170+
* Calculate the gradient magnitude.
171+
*/
172+
void sobel_grad_mag(Image *G, Image G_y, Image G_x) {
173+
int i, j;
174+
175+
for (i = 0; i < G_y.row; i++) {
176+
for (j = 0; j < G_y.col; j++) {
177+
int G_y_sq = G_y.img[i][j] * G_y.img[i][j];
178+
int G_x_sq = G_x.img[i][j] * G_x.img[i][j];
179+
180+
G->img[i][j] = sqrt(G_y_sq + G_x_sq);
181+
}
182+
}
183+
}
184+
185+
/*
186+
* Normalize an image.
187+
*/
188+
void normalize(Image *src) {
189+
int min = 0, max = 0;
190+
int i, j;
191+
int scale;
192+
193+
// Determine the lower and upper bounds of the current values.
194+
for (i = 0; i < src->row; i++) {
195+
for (j = 0; j < src->col; j++) {
196+
if (src->img[i][j] < min)
197+
min = src->img[i][j];
198+
else if (src->img[i][j] > max)
199+
max = src->img[i][j];
200+
}
201+
}
202+
203+
// Normalize the values to between 0 and 255.
204+
for (i = 0; i < src->row; i++) {
205+
for (j = 0; j < src->col; j++) {
206+
src->img[i][j] = (int) floor(255 * ((float) src->img[i][j] / (float) max));
207+
}
208+
}
209+
}
210+
211+
/*
212+
* Main
213+
*/
214+
int main(int argc, char *argv[]) {
215+
int i, j;
216+
int sobel_y[3][3] = {{-1, -2, -1},
217+
{0, 0, 0},
218+
{1, 2, 1}};
219+
int sobel_x[3][3] = {{-1, 0, 1},
220+
{-2, 0, 2},
221+
{-1, 0, 1}};
222+
223+
Image src;
224+
Image G_y;
225+
Image G_x;
226+
Image out;
227+
228+
if (argc < 2) {
229+
fprintf(stderr, "Pass the name of a PGM P5 file.\n");
230+
return 1;
231+
}
232+
233+
// Read source PGM file
234+
if (read_PGM(argv[1], &src))
235+
return 1;
236+
237+
// Initialize all the matrices to be of the same size as the source image.
238+
init_matrix(src, &G_y);
239+
init_matrix(src, &G_x);
240+
init_matrix(src, &out);
241+
242+
// Convolve the Sobel filters with the source image
243+
convolve(sobel_y, src, &G_y);
244+
convolve(sobel_x, src, &G_x);
245+
246+
// Calculate the gradient magnitude and put it in out.
247+
sobel_grad_mag(&out, G_y, G_x);
248+
249+
// Normalize values to 0-255
250+
normalize(&G_y);
251+
normalize(&G_x);
252+
normalize(&out);
253+
254+
// Write final output PGMs
255+
if (write_PGM("g_y.pgm", G_y))
256+
return 1;
257+
if (write_PGM("g_x.pgm", G_x))
258+
return 1;
259+
if (write_PGM("out.pgm", out))
260+
return 1;
261+
262+
// Free the matrices
263+
dealloc_matrix(src.img, src.row);
264+
dealloc_matrix(G_y.img, 4);
265+
dealloc_matrix(G_x.img, 4);
266+
dealloc_matrix(out.img, out.row);
267+
268+
return 0;
269+
}

0 commit comments

Comments
 (0)