OpenCv之边缘检测Sobel算子


首先讲一下我对边缘检测原理的理解。一共分4步进行理解

  • 图像数据
  • 检测数据
  • 形成数据
  • 展示数据

图像数据

想要处理图像,首先要了解图像在内存中是如何存储的。图像是以矩阵的形式进行存储,类似一个表格,图像大小代表了表格的几行几列,每一个格子为一个像素点,像素点代表了这一个点的颜色。像素点有多种类型,单通道(灰色),3通道(RGB)等,不同的类型所占据的字节数也可能是不一致的。

检测数据

此文的所讲的算法的核心就是检测数据,检测数据有很多种方式,Sobel算子采用3*3求导的方式进行检测。下面出自网络:

        首先,我们来开一下计算机是如何检测边缘的。以灰度图像为例,它的理论基础是这样的,如果出现一个边缘,那么图像的灰度就会有一定的变化,为了方便假设由黑渐变为白代表一个边界,那么对其灰度分析,在边缘的灰度函数就是一个一次函数y=kx,对其求一阶导数就是其斜率k,就是说边缘的一阶导数是一个常数,而由于非边缘的一阶导数为零,这样通过求一阶导数就能初步判断图像的边缘了。通常是X方向和Y方向的导数,也就是梯度。理论上计算机就是通过这种方式来获得图像的边缘。

        但是,具体应用到图像中你会发现这个导数是求不了的,因为没一个准确的函数让你去求导,而且计算机在求解析解要比求数值解麻烦得多,所以就想到了一种替代的方式来求导数。就是用一个3×3的窗口来对图像进行近似求导。拿对X方向求导为例,某一点的导数为第三行的元素之和减去第一行元素之和,这样就求得了某一点的近似导数。其实也很好理解为什么它就近似代表导数,导数就代表一个变化率,从第一行变为第三行,灰度值相减,当然就是一个变化率了。这就是所谓的Prewitt算子。这样近似X方向导数就求出来了。Y方向导数与X方向导数求法相似,只不过是用第三列元素之和减去第一列元素之和。X方向和Y方向导数有了,那么梯度也就出来了。这样就可以找出一幅图中的边缘了。 还有一个问题,由于求的是3×3中心点的导数,所以给第二列加了一个权重,它的权重为2,第一列和第三列的权重为1,好了,这就是Sobel算子了。相比Prewitt算子,Sobel的抗噪能力更强

形成数据

在第二点中数据处理结果会形成新的像素点,形成新的图像,也就是我们想要得到的图像,重点提一下,像素点类型一般来说是8位无符号数IPL_DEPTH_8U,但是这里的求导结果会有负值,导致类型不满足条件会报错,这时接收图像是类型应该相应调整IPL_DEPTH_16S,或者其他满足条件的类型。

展示数据(形成图像)

就是图像转数据,数据转图像,详情看代码,重点说明要注意,像素点类型不一致会导致运行报错,在显示前要进行数据类型转换。

效果图


运行代码

xx.h
#pragma once
#include "cv.h"
#include <opencv2/highgui/highgui.hpp>  
#include "main.h"
void mainCv();

xx.cpp
#include "opencvCv.h"
using namespace cv;
void jSobel() {
	IplImage *frame, *gray, *sobel;
	frame = cvLoadImage("wood.jpg");//加载图像
	gray = cvCreateImage(cvGetSize(frame), frame->depth, 1);
	sobel = cvCreateImage(cvGetSize(frame), IPL_DEPTH_16S, 1);
	cvNamedWindow("frame");
	cvNamedWindow("gray");
	cvNamedWindow("sobel");
	cvCvtColor(frame, gray, CV_BGR2GRAY);//转为灰度
	cvSobel(gray, sobel, 1, 0, 3);

	IplImage *sobel8u = cvCreateImage(cvGetSize(sobel), IPL_DEPTH_8U, 1);
	cvConvertScaleAbs(sobel, sobel8u, 1, 0);
	cvShowImage("frame", frame);//显示图像
	cvShowImage("gray", gray);
	cvShowImage("sobel", sobel8u);
	cvWaitKey(0);//等待
	cvReleaseImage(&frame);
	cvReleaseImage(&gray);
	cvReleaseImage(&sobel);
	cvDestroyWindow("frame");
	cvDestroyWindow("gray");
	cvDestroyWindow("sobel");
}

交流邮箱:
1020627740@qq.com


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风晴03

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值