c语言实现canny算子边缘检测代码
时间: 2023-09-19 14:12:47 浏览: 105
以下是使用C语言实现Canny算子边缘检测的代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define WIDTH 512
#define HEIGHT 512
int sobel_x[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
int sobel_y[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};
void gaussian_filter(float *img, float *output, int width, int height, float sigma) {
int i, j, k, l;
int r = ceil(3 * sigma);
float sum = 0.0, val = 0.0;
float *kernel = (float*) malloc((2 * r + 1) * sizeof(float));
for (i = -r; i <= r; i++) {
val = exp(-(i * i) / (2 * sigma * sigma));
kernel[i + r] = val;
sum += val;
}
for (i = 0; i < 2 * r + 1; i++)
kernel[i] /= sum;
for (i = r; i < height - r; i++) {
for (j = r; j < width - r; j++) {
val = 0.0;
for (k = -r; k <= r; k++) {
for (l = -r; l <= r; l++) {
val += img[(i + k) * width + (j + l)] * kernel[k + r] * kernel[l + r];
}
}
output[i * width + j] = val;
}
}
free(kernel);
}
void sobel_filter(float *img, float *output, int width, int height) {
int i, j, k, l;
float gx = 0.0, gy = 0.0, val = 0.0;
float max_val = 0.0;
float angle = 0.0;
float *magnitude = (float*) malloc(width * height * sizeof(float));
float *theta = (float*) malloc(width * height * sizeof(float));
for (i = 1; i < height - 1; i++) {
for (j = 1; j < width - 1; j++) {
gx = 0.0;
gy = 0.0;
for (k = -1; k <= 1; k++) {
for (l = -1; l <= 1; l++) {
gx += img[(i + k) * width + (j + l)] * sobel_x[k + 1][l + 1];
gy += img[(i + k) * width + (j + l)] * sobel_y[k + 1][l + 1];
}
}
magnitude[i * width + j] = sqrt(gx * gx + gy * gy);
theta[i * width + j] = atan2(gy, gx);
max_val = fmax(max_val, magnitude[i * width + j]);
}
}
for (i = 1; i < height - 1; i++) {
for (j = 1; j < width - 1; j++) {
angle = theta[i * width + j] * 180 / M_PI;
if ((angle < -22.5 && angle > -67.5) || (angle > 22.5 && angle < 67.5)) {
val = (magnitude[(i - 1) * width + (j - 1)] + magnitude[(i + 1) * width + (j + 1)]) / 2.0;
} else if ((angle < 22.5 && angle > -22.5) || (angle > 157.5 || angle < -157.5)) {
val = (magnitude[(i - 1) * width + j] + magnitude[(i + 1) * width + j]) / 2.0;
} else if ((angle < -112.5 && angle > -157.5) || (angle > 112.5 && angle < 157.5)) {
val = (magnitude[i * width + (j - 1)] + magnitude[i * width + (j + 1)]) / 2.0;
} else {
val = (magnitude[(i + 1) * width + (j - 1)] + magnitude[(i - 1) * width + (j + 1)]) / 2.0;
}
output[i * width + j] = val / max_val;
}
}
free(magnitude);
free(theta);
}
void threshold(float *img, float *output, int width, int height, float low, float high) {
int i, j;
float val = 0.0;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
val = img[i * width + j];
if (val > high) {
output[i * width + j] = 1.0;
} else if (val < low) {
output[i * width + j] = 0.0;
} else {
if ((img[(i - 1) * width + j - 1] > high) || (img[(i - 1) * width + j] > high) ||
(img[(i - 1) * width + j + 1] > high) || (img[i * width + j - 1] > high) ||
(img[i * width + j + 1] > high) || (img[(i + 1) * width + j - 1] > high) ||
(img[(i + 1) * width + j] > high) || (img[(i + 1) * width + j + 1] > high)) {
output[i * width + j] = 1.0;
} else {
output[i * width + j] = 0.0;
}
}
}
}
}
int main() {
int i, j;
float *img = (float*) malloc(WIDTH * HEIGHT * sizeof(float));
float *output = (float*) malloc(WIDTH * HEIGHT * sizeof(float));
float *temp = (float*) malloc(WIDTH * HEIGHT * sizeof(float));
FILE *fp = fopen("lena.raw", "rb");
fread(img, sizeof(float), WIDTH * HEIGHT, fp);
fclose(fp);
gaussian_filter(img, temp, WIDTH, HEIGHT, 1.0);
sobel_filter(temp, output, WIDTH, HEIGHT);
threshold(output, temp, WIDTH, HEIGHT, 0.2, 0.3);
fp = fopen("canny.raw", "wb");
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < WIDTH; j++) {
fwrite(&temp[i * WIDTH + j], sizeof(float), 1, fp);
}
}
fclose(fp);
free(img);
free(output);
free(temp);
return 0;
}
```
这个实现过程和上面提到的基本步骤是一致的,其中包括高斯滤波、Sobel算子边缘检测、非极大值抑制和双阈值处理。请注意,上面的代码仅供参考,实际应用中可能需要进行一些调整和优化。
阅读全文