c语言数字图像处理(九):边缘检测
背景知识
边缘像素是图像中灰度突变的像素,而边缘是连接边缘像素的集合。边缘检测是设计用来检测边缘像素的局部图像处理方法。
孤立点检测
使用<https://www.cnblogs.com/GoldBeetle/p/9744625.html>中介绍的拉普拉斯算子
输出图像为
卷积模板
之前有过代码实现,这篇文章中不再进行测试
基本边缘检测
图像梯度
梯度向量大小
在图像处理过程中,因平方和和开方运算速度较慢,因此简化为如下计算方法
梯度向量方向与x轴夹角
对应与不同的偏导数计算方法,得出边缘检测的不同模板
检测垂直或水平边缘
原图
使用Sobel模板检测水平边缘
使用Sobel模板检测垂直边缘
两者相加
代码实现
void edge_detection(short** in_array, short** out_array, long height, long width)
{
short gx = , gy = ;
short** a_soble1;
short** a_soble2; a_soble1 = allocate_image_array(, );
a_soble2 = allocate_image_array(, );
for (int i = ; i < ; i++){
for (int j = ; j < ; j++){
a_soble1[i][j] = soble1[i][j];
a_soble2[i][j] = soble2[i][j];
}
}
for (int i = ; i < height; i++){
for (int j = ; j < width; j++){
gx = convolution(in_array, i, j, height, width, a_soble1, );
gy = convolution(in_array, i, j, height, width, a_soble2, );
// out_array[i][j] = gx;
// out_array[i][j] = gy;
out_array[i][j] = gx + gy;
if (out_array[i][j] < )
out_array[i][j] = ;
else if (out_array[i][j] > 0xff)
out_array[i][j] = 0xff;
}
}
free_image_array(a_soble1, );
free_image_array(a_soble2, );
}
检测对角边缘
Sobel 45°检测模板
Sobel -45°检测模板
两者相加
代码实现通上,只需替换模板值即可
Marr-Hildreth边缘检测算法
1. 对二维高斯函数进行取样,得高斯低通滤波器,对输入图像滤波,滤波器模板大小为大于等于6*σ的最小奇整数
算法实现
void generate_gaussian_filter(double** gaussian_filter, long sigma)
{
double x, y;
long filter_size = * sigma + ; for (int i = ; i < filter_size; i++){
for (int j = ; j < filter_size; j++){
x = i - filter_size / ;
y = j - filter_size / ;
gaussian_filter[i][j] = exp(-1.0 * ((pow(x, ) + pow(y, )) / * sigma * sigma));
}
}
}
2. 计算第一步得到图像的拉普拉斯,利用如下模板
算法实现
void laplace(short** in_array, short** out_array, long height, long width)
{
short** a_sharpen; a_sharpen = allocate_image_array(, );
for (int i = ; i < ; i++){
for (int j = ; j < ; j++){
a_sharpen[i][j] = sharpen[i][j];
}
}
for (int i = ; i < height; i++){
for (int j = ; j < width; j++){
out_array[i][j] = convolution(in_array, i, j, height, width, a_sharpen, );
}
}
free_image_array(a_sharpen, );
}
运行结果
3. 寻找零交叉,对任意像素p,测试上/下,左/右,两个对角线四个位置,当有两对符号不同并且绝对值差大于某一阈值时为零交叉点
算法实现
int is_cross(short** in_array, long row, long column)
{
int cross_num = ; if (in_array[row-][column-] * in_array[row+][column+] < &&
abs(abs(in_array[row-][column-]) - abs(in_array[row+][column+])) > 0x66)
cross_num++;
if (in_array[row-][column] * in_array[row+][column] < &&
abs(abs(in_array[row-][column]) - abs(in_array[row+][column])) > 0x66)
cross_num++;
if (in_array[row-][column+] * in_array[row+][column-] < &&
abs(abs(in_array[row-][column+]) - abs(in_array[row+][column-])) > 0x66)
cross_num++;
if (in_array[row][column-] * in_array[row][column+] < &&
abs(abs(in_array[row][column-]) - abs(in_array[row][column+])) > 0x66)
cross_num++; if (cross_num >= )
return ;
else
return ;
}
void marr(short** in_array, short** out_array, long height, long width)
{
long sigma = ;
long filter_size = * sigma + ;
double** gaussian_filter;
short **gauss_array, **laplace_array; gaussian_filter = allocate_double_array(filter_size, filter_size);
gauss_array = allocate_image_array(height, width);
laplace_array = allocate_image_array(height, width);
generate_gaussian_filter(gaussian_filter, sigma); for (int i = ; i < height; i++){
for (int j = ; j < width; j++){
gauss_array[i][j] = convolutiond(in_array, i, j, height, width, gaussian_filter, filter_size);
}
}
printf("Gasuuian filter done\n");
laplace(gauss_array, laplace_array, height, width);
printf("Laplace done\n");
zero_cross(laplace_array, out_array, height, width);
printf("Zero cross done\n"); free_double_array(gaussian_filter, filter_size);
free_image_array(gauss_array, height);
free_image_array(laplace_array, height);
}
最终运行结果
可以看出,该算法检测出的边缘更加符合物体的真实边缘,但是这些边缘是由离散的点构成的,因此需要进行边缘连接来进一步加工,本文对此不再进行详述,读者有兴趣可以进行更加深入的研究。
c语言数字图像处理(九):边缘检测的更多相关文章
- c语言数字图像处理(三):仿射变换
仿射变换及坐标变换公式 几何变换改进图像中像素间的空间关系.这些变换通常称为橡皮模变换,因为它们可看成是在一块橡皮模上印刷一幅图像,然后根据预定的一组规则拉伸该薄膜.在数字图像处理中,几何变换由两个基 ...
- c语言数字图像处理(二):图片放大与缩小-双线性内插法
图像内插 假设一幅大小为500 * 500的图像扩大1.5倍到750 * 750,创建一个750 * 750 的网格,使其与原图像间隔相同,然后缩小至原图大小,在原图中寻找最接近的像素(或周围的像素) ...
- c语言数字图像处理(一):bmp图片格式及灰度图片转换
本篇文章首先介绍了bmp图片格式,主要参考wiki上的内容,包括bmp文件的存储方式,对于一些常见的bmp文件格式都给了例子,并且对8位 16位RGB555 16位RGB565格式的bmp文件进行了简 ...
- c语言数字图像处理(十):阈值处理
定义 全局阈值处理 假设某一副灰度图有如下的直方图,该图像由暗色背景下的较亮物体组成,从背景中提取这一物体时,将阈值T作为分割点,分割后的图像g(x, y)由下述公式给出,称为全局阈值处理 多阈值处理 ...
- c语言数字图像处理(八):噪声模型及均值滤波器
图像退化/复原过程模型 高斯噪声 PDF(概率密度函数) 生成高斯随机数序列 算法可参考<http://www.doc.ic.ac.uk/~wl/papers/07/csur07dt.pdf&g ...
- c语言数字图像处理(七):频率域滤波
代码运行了两个小时才出的结果,懒得测试了,这一部分先鸽了,等对DFT算法进行优化后再更
- c语言数字图像处理(六):二维离散傅里叶变换
基础知识 复数表示 C = R + jI 极坐标:C = |C|(cosθ + jsinθ) 欧拉公式:C = |C|ejθ 有关更多的时域与复频域的知识可以学习复变函数与积分变换,本篇文章只给出DF ...
- c语言数字图像处理(五):空间滤波
空间滤波原理 使用大小为m*n的滤波器对大小为M*N的图像进行线性空间滤波,将滤波器模板乘以图像中对应灰度值,相加得模板中心灰度值 a = (m-1)/2, b = (n-1)/2 若f(x+s, y ...
- c语言数字图像处理(四):灰度变换
灰度变换 灰度变换函数 s = T(r) 其中r为输入图像在(x, y)点处的灰度值,s为输出图像在(x, y)点处的灰度值 灰度变换的作用 上图所示的两幅T(s)函数的图像曲线,第一幅图可以增强 ...
随机推荐
- 手动安装gradle
在学习andorid studio时发现编译超级无比的慢,网上有文说是因为gradle的原因,使用离线gradle可以大幅提高编译速度,准备尝试下看看如何.由于gradle的资料都是英文,而我又是英文 ...
- 关于第三次寒假作业之C++Calculator项目的情况:
一.仓库地址: object-oriented: 二.作业要求: Calculator: 三.完成本次作业的情况及感受: 刚接触到这个题目的时候,自己就是那丈二的和尚,摸不着头脑,由于自己视频找得比较 ...
- [微信小程序直播平台开发]___(二)Nginx+rtmp在Windows中的搭建
1.一个可以忽略的前言 Nginx (engine x) 是一个高性能的HTTP和反向代理服务,也是一个IMAP/POP3/SMTP服务.Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Ramble ...
- Linux新建用户没有设置密码
只要你能登陆root账户就行 登陆root账户 输入 echo "密码“ | passwd --stdin 用户名
- hihoCoder1343 : Stable Members【BFS拓扑排序】
题目链接:https://hihocoder.com/problemset/problem/1343 #1343 : Stable Members 时间限制:10000ms 单点时限:1000ms 内 ...
- 4-5 R语言函数 split
#split根据因子或因子列表将 向量或其他对象分组 #通常与lapply一起使用 #split(参数):split(向量/列表/数据框,因子/因子列表) > x <- c(rnorm(5 ...
- 2.2 IPython基础
2.2 IPython基础 1 Running the IPython Shell (运行IPython Shell) 可以通过命令行启动IPython,就像启动标准的Python解释器一样,直接在t ...
- 在linux中禁用一块硬盘
笔记本采用固态加机械的硬盘组合使用中完全用不到机械部分 但它总是在启动后运行并发出响声 1 启动后的禁用 无需重启 (sdx是你的磁盘 udev的更新可能会导致磁盘重新出现 在向系统添加/删除磁盘也 ...
- 打包dll发布到nuget服务器
几个月前上传过一次nuget包,结果好久不用,今天想更新下,完全忘记了怎么用了,又是一顿查,所以决定记录下来,当然这可能不是一个傻瓜式的教程,但聪明的你们应该能够看明白的,因为整体操作还是很简单的 好 ...
- python110道面试题
1.一行代码实现1--100之和 利用sum()函数求和 2.如何在一个函数内部修改全局变量 利用global 修改全局变量 3.列出5个python标准库 os:提供了不少与操作系统相关联的函数 s ...