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

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

图像数据


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


检测数据


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


http://wiki.opencv.org.cn/index.php/%E9%A6%96%E9%A1%B5



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

  

形成数据


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


展示数据(形成图像)


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



效果图




opencv 边缘膨胀 opencv sobel边缘检测_opencv 边缘膨胀



运行代码


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");
}