C++OpenCV系统学习(8)——图像边缘填充、边缘提取、边缘检测

1.图像边缘填充

1.1卷积边界问题

图像卷积的时候边界像素不被卷积操作,原因在于边界像素没有完全跟kernel重叠,只有当3X3的滤波时候有一个像素的边缘没有被处理,5x5滤波的时候有两个像素边缘没有处理。

1.2.处理边缘

在卷积开始之前增加边缘像素,填充的像素值为0或者RGB黑色,比如3x3在四周各填充1各像素的边缘,这样就确保图像的边缘被处理,在卷积处理hi后再去掉这些边缘,openCV中默认的处理方式就是:BORDER_DEFAULT,此外还有常用

  • BOEDER_CONSTANT-填充边缘用指定像素
  • BOEDER_REPLICATE-填充边缘像素用已知的边缘像素
  • BOEDER_WRAP-用另外一边的像素来补充填充

1.3.给图像添加边缘的API

copyMakeBorder(
Mat src,//输入图像
Mat dst,//添加边缘图像
int top,//边缘长度,一般上下左右都取相同值
int bottom,
int left,
int right,
int borderType//边缘类型
Scalar value

)

1.4代码

void MyApi::image_edge_processing(Mat& image)
{
	//每半秒中图像的边缘就会变化一次,我们也可以通过按键选择变化的类型
	Mat dst;
	int top = (int)(0.05 * image.rows);
	int bottom = (int)(0.05 * image.rows);
	int left = (int)(0.05 * image.cols);
	int right = (int)(0.05 * image.cols);
	RNG rng(12345);
	int borderType = BORDER_DEFAULT;

	int c = 0;
	while (true)
	{
		c = waitKey(500);
		//ESC
		if ((char)c == 27)
		{
			break;
		}
		if ((char)c == 'r')
		{
			borderType = BORDER_REPLICATE;
		}
		else if ((char)c == 'w')
		{
			borderType == BORDER_WRAP;
		}
		else if ((char)c == 'c')
		{
			borderType == BORDER_CONSTANT;
		}
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		copyMakeBorder(image, dst, top, bottom, left, right, borderType, color);
		imshow("OUTPUT", dst);
	}

}

2.图像边缘提取——卷积的应用

C++OpenCV系统学习(8)——图像边缘填充、边缘提取、边缘检测_第1张图片

 边缘:

  • 边缘是什么:是像素值发生跃迁的地方,是图像的显著特征之一,在图像特征提取、对象检测、模式识别等方面都有重要的作用。
  • 如何捕捉/提取边缘——对图像求他的一阶导数,delta = f(x)-f(x-1).delta越大说明像素在方向变化越大,边缘信号越强 
  • 我们可以选择利用一些算子如Sobel算子等

2.1Sobel算子

  • 是离散微分算子,用来计算图像灰度的近似梯度
  • Sobel算子功能集合高斯平滑和微分求导
  • 又称为一阶微分算子(Laplace是二阶算子),求导算子,在水平和垂直两个方向上求导,得到图像x方向与y方向梯度图像C++OpenCV系统学习(8)——图像边缘填充、边缘提取、边缘检测_第2张图片

 水平梯度在水平方向乘以2为了扩大水平方向差异,垂直方向同理。

改进版本的Sobel算子:

             C++OpenCV系统学习(8)——图像边缘填充、边缘提取、边缘检测_第3张图片

 相关的API 

cv::Sobel(inputArray src,OutputArray dst,
int depth,//输出图像深度
int dx,//x和y方向的几节导数,选择1
 int dy,
int ksize,//Sobel算子kernel大小,必须是1,3,5,7
double scale=1
double delta =0
int borderType = BORDEDR_DEFAULT
)

C++OpenCV系统学习(8)——图像边缘填充、边缘提取、边缘检测_第4张图片

深度一般选择CV_8U中的 CV_16S或者CV_32F

步骤:

  1. 高斯平滑
  2. 转灰度
  3. 求梯度,分别在x和Y方向上的
  4. 振幅图片(综合X和Y方向上的)
void MyApi::image_edge_extract(Mat& image)
{
	Mat gray_image, dst;
	GaussianBlur(image, dst, Size(5, 5), 0, 0);
	cvtColor(dst, gray_image, COLOR_BGR2GRAY);
	Mat xgard, ygrad;
	Sobel(gray_image, xgard, CV_16S, 1, 0, 3);
	Sobel(gray_image, ygrad, CV_16S, 0, 1, 3);
	//convert(ScaleAbs());
    //必须取绝对值不然看不见效果
	convertScaleAbs(xgard, xgard);
	convertScaleAbs(ygrad, ygrad);
	//x方向梯度
	imshow("xgrad", xgard); 
	//y方向梯度
	imshow("ygrad", ygrad);
	
	//xy方向梯度
	Mat xygrad;
	addWeighted(xgard, 0.5, ygrad, 0.5,0,xygrad);
	imshow("xygrad", xygrad);
}

 

2.2Laplace算子

2.2.1概述

C++OpenCV系统学习(8)——图像边缘填充、边缘提取、边缘检测_第5张图片

    C++OpenCV系统学习(8)——图像边缘填充、边缘提取、边缘检测_第6张图片

2.2.2处理流程

  1.  高斯模糊去噪声GaussianBlue()

  2. 转换为灰度图像cvtColor()

  3. 拉普拉斯二阶导数计算Laplacian()

  4. 取绝对值convertScaleAbs()

  5. 显示结果

void MyApi::image_edge_extraxt_Laplance(Mat& image)
{
	Mat gray_image, edge_image, dst;
	GaussianBlur(image, dst, Size(3, 3), 0, 0);
	cvtColor(dst, gray_image, COLOR_BGR2GRAY);
	Laplacian(gray_image, edge_image, CV_16S, 3);
	convertScaleAbs(edge_image, edge_image);
	imshow("output", edge_image);
}

为了让效果更佳的明显我们选用了二值化操作:

 图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出明显的黑白效果。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。OpenCV中提供了函数cv::threshold();

加一句:

C++OpenCV系统学习(8)——图像边缘填充、边缘提取、边缘检测_第7张图片

通过二值化后:

C++OpenCV系统学习(8)——图像边缘填充、边缘提取、边缘检测_第8张图片 3.Canny边缘检测

3.1概述

Canny1986年提出的是边缘检测算法,是一个很好的边缘检测器,很常用的图像处理方法

3.2步骤

  1. 高斯模糊-GaussianBlur
  2. 灰度转换-cvtColor
  3. 计算梯度-Sobel/Scharr
  4. 非最大信号抑制
  5. 高低阈值输出二值图像

 3.3非最大信号一抑制C++OpenCV系统学习(8)——图像边缘填充、边缘提取、边缘检测_第9张图片

 3.4高低阈值输出二值图像                      

C++OpenCV系统学习(8)——图像边缘填充、边缘提取、边缘检测_第10张图片

 3.5相关API

Canny(
    InputArray src,
    OutputArray edges,
    double threshold1,//低阈值,常取高于之的1/2或者1/3
    double threshold2,//高阈值
    int aptertureSize,//Sobel算子的size,通常3x3取值为3
    bool L2gradient//选择true表示L2来归一化,否则用L1来归一化
)

          C++OpenCV系统学习(8)——图像边缘填充、边缘提取、边缘检测_第11张图片

你可能感兴趣的:(QT模块,qt,c++)