Canny边缘检测+孔洞填充

使用C++、opencv进行边缘检测+空洞填充

相关重要API:

Mat getStructuringElement(int shape, Size esize, Point anchor = Point(-1, -1));

getStructuringElement函数会返回指定形状和尺寸的结构元素,返回类型为Mat

第一个参数表示内核的形状,有三种形状可以选择:

矩形:MORPH_RECT;

交叉形:MORPH_CROSS;

椭圆形:MORPH_ELLIPSE;

第二和第三个参数分别是内核的尺寸以及锚点的位置。

一般在调用erode以及dilate函数之前,先定义一个Mat类型的变量来获得getStructuringElement函数的返回值。对于锚点的位置,有默认值Point(-1,-1),表示锚点位于中心点。element形状唯一依赖锚点位置,其他情况下,锚点只是影响了形态学运算结果的偏移。

----------------------------------------------------------

void morphologyEx(InputArray src,//输入图像
    OutputArray dst,//输出图像
    int op, //标识符,表示形态学运算的类型
    InputArray kernel,//结构元素,即用于卷积的内核
    Point anchor = Point(-1, -1),//默认值,锚点位于中心
    int iterations = 1,//默认值,迭代次数
    int borderType = BORDER_CONSTANT,//默认值
    const Scalar& borderValue = morphologyDefaultBorderValue());//默认值

第一个参数,输入图像
第二个参数,输出图像
第三个参数,使用的形态学方法,有以下几种:

MORPH_OPEN – 开运算(Opening operation)
开运算是对图像先腐蚀再膨胀,可以排除小团的物体;

 MORPH_CLOSE – 闭运算(Closing operation)
闭运算是对图像先膨胀再腐蚀,可以排除小型黑洞;

MORPH_GRADIENT -形态学梯度(Morphological gradient)
返回图片为膨胀图与腐蚀图之差,可以保留物体的边缘轮廓;

MORPH_TOPHAT - “顶帽”(“Top hat”)
返回图像为原图像与开运算结果图之差;

MORPH_BLACKHAT - “黑帽”(“Black hat“)
返回图片为闭运算结果图与原图像之差。

第四个参数,InputArray类型的kernel,形态学运算的内核。若为NULL时,表示的是使用参考点位于中心3x3的核。
第五个参数,Point类型的anchor,锚的位置,其有默认值(-1,-1),表示锚位于中心。
第六个参数,int类型的iterations,迭代使用函数的次数,默认值为1。
第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。它有默认值BORDER_ CONSTANT。
第八个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue()。
------------------------------------------------------

#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <vector>
using namespace std;
#define zoom 4 // 缩放因子, 将大图像缩小 n 倍显示

using namespace cv;
using namespace std;

// 填充holes
void fillHole(const Mat srcBw, Mat &dstBw);

int main()
{
	// 【1】读入图像
	Mat srcImage;
	srcImage = imread("D:\\DSC_0506.JPG");
	if (!srcImage.data) { 
		//处理错误
		cout << "读取图片错误!" << endl;
		system("pause");
		return 0;
	}

	//【2】将图片转为灰度图
	cvtColor(srcImage, srcImage, COLOR_BGR2GRAY);

	Mat temp;
	temp = srcImage;
	resize(temp, temp, Size(temp.cols / zoom, temp.rows / zoom), (0, 0), (0, 0), 3);
	imshow("灰度图", temp);

	// 【3】canny算子边缘检测
	Mat edge;
	blur(srcImage, edge, Size(3, 3));//3x3内核降噪
	Canny(srcImage, edge, 150, 100, 3);
	temp = edge;
	resize(edge, temp, Size(temp.cols / zoom, temp.rows / zoom), (0, 0), (0, 0), 3);
	imshow("canny算子边缘检测", temp);

	//【4】膨胀操作, 填充边缘缝隙
	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));

	for (int i = 0; i < 3; i++) {
		morphologyEx(edge, edge, MORPH_DILATE,element);
	}
	temp = edge;
	resize(edge, temp, Size(temp.cols / zoom, temp.rows / zoom), (0, 0), (0, 0), 3);
	imshow("膨胀操作效果图", temp);

	// 【5】Holes填充
	for (int i = 0; i < 10; i++) // 填充10次
	{
		fillHole(edge, edge);
	}
	temp = edge;
	resize(edge, temp, Size(temp.cols / zoom, temp.rows / zoom), (0, 0), (0, 0), 3);
	imshow("【Holes填充图】", temp);

	waitKey(0); // 等待按键结束
	return 0;
}

// 填充Holes
void fillHole(const Mat srcBw, Mat &dstBw)
{
	Size m_Size = srcBw.size();
	Mat Temp = Mat::zeros(m_Size.height + 2, m_Size.width + 2, srcBw.type());//延展图像
	srcBw.copyTo(Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)));

	floodFill(Temp, Point(0, 0), Scalar(255));

	Mat cutImg;//裁剪延展的图像
	Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)).copyTo(cutImg);

	dstBw = srcBw | (~cutImg);
}

原图:

canny边缘检测效果图:

边缘膨胀效果图:

空洞填充效果图:

 相关参考:https://blog.csdn.net/kksc1099054857/article/details/76569718

                   https://blog.csdn.net/jiangjiao4726/article/details/75571014

猜你喜欢

转载自blog.csdn.net/Lemon_jay/article/details/89316274