canny算子c代码
时间: 2023-08-04 14:09:21 浏览: 73
以下是使用C语言实现Canny算子的基本步骤:
1. 对图像进行灰度化处理。
2. 对灰度图像进行高斯滤波,以去除噪声。
3. 计算图像中每个像素的梯度幅值和方向。
4. 对梯度方向进行非极大值抑制,以保留边缘的细节。
5. 应用双阈值算法,将像素分类为强边缘、弱边缘和非边缘。
6. 进行边缘连接,以连接强边缘和相邻的弱边缘。
以下是使用C语言实现Canny算子的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
#define KERNEL_SIZE 5
#define THRESHOLD_LOW 50
#define THRESHOLD_HIGH 150
int width, height, channels;
unsigned char *image, *gray, *smooth, *dx, *dy, *edge;
float *magnitude, *orientation;
void grayscale()
{
for (int i = 0; i < width * height; i++)
{
gray[i] = (unsigned char)(0.2126 * image[3 * i] + 0.7152 * image[3 * i + 1] + 0.0722 * image[3 * i + 2]);
}
}
void gaussian()
{
float kernel[KERNEL_SIZE][KERNEL_SIZE] = {
{1, 4, 7, 4, 1},
{4, 16, 26, 16, 4},
{7, 26, 41, 26, 7},
{4, 16, 26, 16, 4},
{1, 4, 7, 4, 1}
};
float sum = 273.0;
for (int i = 2; i < height - 2; i++)
{
for (int j = 2; j < width - 2; j++)
{
float value = 0.0;
for (int k = -2; k <= 2; k++)
{
for (int l = -2; l <= 2; l++)
{
value += kernel[k + 2][l + 2] * gray[(i + k) * width + j + l];
}
}
smooth[i * width + j] = (unsigned char)(value / sum);
}
}
}
void sobel()
{
for (int i = 1; i < height - 1; i++)
{
for (int j = 1; j < width - 1; j++)
{
int dx_value = -dx[-width + j - 1] - 2 * dx[-1 + j] - dx[width + j - 1] + dx[-width + j + 1] + 2 * dx[1 + j] + dx[width + j + 1];
int dy_value = -dy[-width + j - 1] - 2 * dy[-width + j] - dy[-width + j + 1] + dy[width + j - 1] + 2 * dy[width + j] + dy[width + j + 1];
magnitude[i * width + j] = sqrt(dx_value * dx_value + dy_value * dy_value);
orientation[i * width + j] = atan2(dy_value, dx_value);
}
}
}
void non_max_suppression()
{
for (int i = 1; i < height - 1; i++)
{
for (int j = 1; j < width - 1; j++)
{
float angle = orientation[i * width + j] * 180 / M_PI;
if (angle < 0)
{
angle += 180;
}
int q = 255;
int r = 255;
if ((angle >= 0 && angle < 22.5) || (angle >= 157.5 && angle <= 180))
{
q = magnitude[i * width + j + 1];
r = magnitude[i * width + j - 1];
}
else if (angle >= 22.5 && angle < 67.5)
{
q = magnitude[(i + 1) * width + j - 1];
r = magnitude[(i - 1) * width + j + 1];
}
else if (angle >= 67.5 && angle < 112.5)
{
q = magnitude[(i + 1) * width + j];
r = magnitude[(i - 1) * width + j];
}
else if (angle >= 112.5 && angle < 157.5)
{
q = magnitude[(i - 1) * width + j - 1];
r = magnitude[(i + 1) * width + j + 1];
}
if (magnitude[i * width + j] >= q && magnitude[i * width + j] >= r)
{
edge[i * width + j] = (unsigned char)magnitude[i * width + j];
}
else
{
edge[i * width + j] = 0;
}
}
}
}
void hysteresis()
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (edge[i * width + j] >= THRESHOLD_HIGH)
{
edge[i * width + j] = 255;
}
else if (edge[i * width + j] < THRESHOLD_LOW)
{
edge[i * width + j] = 0;
}
else
{
int is_edge = 0;
for (int k = -1; k <= 1; k++)
{
for (int l = -1; l <= 1; l++)
{
if (i + k >= 0 && i + k < height && j + l >= 0 && j + l < width)
{
if (edge[(i + k) * width + j + l] >= THRESHOLD_HIGH)
{
is_edge = 1;
}
}
}
}
if (is_edge == 1)
{
edge[i * width + j] = 255;
}
else
{
edge[i * width + j] = 0;
}
}
}
}
}
int main(int argc, char **argv)
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s <image>\n", argv[0]);
return 1;
}
image = stbi_load(argv[1], &width, &height, &channels, 0);
if (image == NULL)
{
fprintf(stderr, "Could not open or find the image!\n");
return 1;
}
gray = (unsigned char *)malloc(width * height * sizeof(unsigned char));
smooth = (unsigned char *)malloc(width * height * sizeof(unsigned char));
dx = (unsigned char *)malloc(width * height * sizeof(unsigned char));
dy = (unsigned char *)malloc(width * height * sizeof(unsigned char));
magnitude = (float *)malloc(width * height * sizeof(float));
orientation = (float *)malloc(width * height * sizeof(float));
edge = (unsigned char *)malloc(width * height * sizeof(unsigned char));
grayscale();
gaussian();
for (int i = 1; i < height - 1; i++)
{
for (int j = 1; j < width - 1; j++)
{
dx[i * width + j] = smooth[i * width + j + 1] - smooth[i * width + j - 1];
dy[i * width + j] = smooth[(i + 1) * width + j] - smooth[(i - 1) * width + j];
}
}
sobel();
non_max_suppression();
hysteresis();
stbi_write_png("edge.png", width, height, 1, edge, width);
stbi_image_free(image);
free(gray);
free(smooth);
free(dx);
free(dy);
free(magnitude);
free(orientation);
free(edge);
return 0;
}
```
在这个示例中,我们使用了stb_image库来读取和写入图像。我们实现了Canny算子的所有步骤,并将结果保存为PNG格式的图像。
阅读全文