Anonymous user
Canny edge detector: Difference between revisions
Small improvements in the C entry
(In the C entry: (int*) is an overkill for 8bpp images. Using (short int*) instead halves memory usage.) |
(Small improvements in the C entry) |
||
Line 15:
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#define MAX_BRIGHTNESS 255
// C99 doesn't define M_PI (GNU-C99 does)
#define M_PI 3.14159265358979323846264338327
Line 65 ⟶ 68:
} rgb_t;
// Use short int instead `unsigned char' so that we can
// store negative values.
typedef short int pixel_t;
Line 93 ⟶ 96:
return NULL;
}
bmpfile_header_t bitmapFileHeader; // our bitmap file header
Line 114 ⟶ 116:
// move file point to the beginning of bitmap data
if (fseek(filePtr, bitmapFileHeader.bmp_offset, SEEK_SET)
fclose(filePtr);
return NULL;
}
// allocate enough memory for the bitmap image data
pixel_t *bitmapImage =
// verify memory allocation
Line 144 ⟶ 149:
}
// Return:
const pixel_t *data)
{
FILE*
if (
return
bmpfile_magic_t mag = {{0x42, 0x4d}};
if (fwrite(&mag
fclose(filePtr);
return true;
}
const uint32_t offset = sizeof(bmpfile_magic_t) +
Line 167 ⟶ 175:
};
if (fwrite(&bmp_fh
fclose(filePtr);
fwrite(bmp_ih, 1, sizeof(bitmap_info_header_t), fp);▼
return true;
}
fclose(filePtr);
return true;
}
// Palette
for (size_t i = 0; i < (1U << bmp_ih->bitspp); i++) {
const rgb_t color = {(uint8_t)i, (uint8_t)i, (uint8_t)i};
if (fwrite(&color
}
// We use int instead of uchar, so we can't write img
// in 1 call any more.
// fwrite(data, 1, bmp_ih->bmp_bytesz,
for (size_t i = 0; i < bmp_ih->bmp_bytesz; i++) {
unsigned char c = (unsigned char)data[i];
if (fwrite(&c, sizeof(unsigned char), 1,
fclose(filePtr);
return true;
}
}
fclose(
return
}
// if
void convolution(const pixel_t *in, pixel_t *out, const float *kernel,
const int nx, const int ny, const int kn,
const bool
{
const int khalf = kn / 2;
float min = FLT_MAX, max = -FLT_MAX;
if (
for (int m = khalf; m < nx - khalf; m++)
for (int n = khalf; n < ny - khalf; n++) {
float pixel = 0.0;
for (int j = -khalf; j <= khalf; j++)
for (int i = -khalf; i <= khalf; i++) {
Line 215 ⟶ 237:
for (int n = khalf; n < ny - khalf; n++) {
float pixel = 0.0;
for (int j = -khalf; j <= khalf; j++)
for (int i = -khalf; i <= khalf; i++) {
Line 222 ⟶ 244:
}
if (
pixel = MAX_BRIGHTNESS * (pixel - min) / (max - min);
out[n * nx + m] = (pixel_t)pixel;
Line 228 ⟶ 250:
}
/*
// http:// www.songho.ca/dsp/cannyedge/cannyedge.html▼
* gaussianFilter:
// determine size of kernel (odd #)▼
// 0.0 <= sigma < 0.5 : 3▼
* kernelSize = 2 * int(2*sigma) + 3;
*/
void gaussian_filter(const pixel_t *in, pixel_t *out,
const int nx, const int ny, const float sigma)
Line 247 ⟶ 271:
fprintf(stderr, "gaussian_filter: kernel size %d, sigma=%g\n",
n, sigma);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
Line 282 ⟶ 306:
pixel_t *out = malloc(bmp_ih->bmp_bytesz * sizeof(pixel_t));
if (
nms == NULL || out == NULL) {
fprintf(stderr, "canny_edge_detection:"
" Failed memory allocation(s).\n");
exit(1);
}
gaussian_filter(in, out, nx, ny, sigma);
Line 290 ⟶ 318:
-2, 0, 2,
-1, 0, 1};
convolution(out, after_Gx, Gx, nx, ny, 3, false);▼
const float Gy[] = { 1, 2, 1,
Line 295 ⟶ 325:
-1,-2,-1};
▲ convolution(out, after_Gx, Gx, nx, ny, 3, false);
convolution(out, after_Gy, Gy, nx, ny, 3, false);
▲ int Gmax = 0;
for (int i = 1; i < nx - 1; i++)
for (int j = 1; j < ny - 1; j++) {
Line 304 ⟶ 332:
// G[c] = abs(after_Gx[c]) + abs(after_Gy[c]);
G[c] = (pixel_t)hypot(after_Gx[c], after_Gy[c]);
▲ if (G[c] > Gmax)
▲ Gmax = G[c];
}
Line 339 ⟶ 365:
// Reuse array
int *edges = (int*) after_Gy;
memset(out, 0, sizeof(pixel_t) * nx * ny);
memset(edges, 0, sizeof(pixel_t) * nx * ny);
// Tracing edges with hysteresis . Non-recursive implementation.
for (int j = 1; j < ny - 1; j++)
for (int i = 1; i < nx - 1; i++) {
Line 394 ⟶ 421:
static bitmap_info_header_t ih;
const pixel_t *in_bitmap_data = load_bmp(argv[1], &ih);
if (in_bitmap_data == NULL) {
fprintf(stderr, "main: BMP image not loaded.\n");
return 1;
}
printf("Info: %d x %d x %d\n", ih.width, ih.height, ih.bitspp);
Line 401 ⟶ 430:
const pixel_t *out_bitmap_data =
canny_edge_detection(in_bitmap_data, &ih, 45, 50, 1.0f);
if (out_bitmap_data == NULL) {
fprintf(stderr, "main: failed canny_edge_detection.\n");
return 1;
}
if (save_bmp("out.bmp", &ih, out_bitmap_data))
fprintf(stderr, "main: BMP image not saved.\n");
return 1;
}
free((pixel_t*)in_bitmap_data);
|