11.2开运算 闭运算 顶帽 黑帽

基本概念

•开运算:先腐蚀后膨胀,用于去除小的噪声点。

•闭运算:先膨胀后腐蚀,用于连接接近的物体。

开运算示例代码

#include "pch.h"

#include<iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;


void opening(const Mat &src, Mat &dst, const Mat &kernel, int iterations) 
{
	Mat temp;
	erode(src, temp, kernel, Point(-1, -1), iterations);
	dilate(temp, dst, kernel, Point(-1, -1), iterations);
}

int main(int argc, char** argv)
{
	/*if (argc != 2) 
	{
		cout << "Usage: ./Opening <Image Path>" << endl;
		return -1;
	}*/

	// 加载图像
	Mat img = imread("877.png", IMREAD_GRAYSCALE);
	if (!img.data) 
	{
		cout << "Error opening image" << endl;
		return -1;
	}

	// 定义结构元素
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));

	// 初始化输出矩阵
	Mat opened;

	// 执行开运算
	opening(img, opened, kernel, 1);

	// 显示结果
	namedWindow("Original Image", WINDOW_NORMAL);
	imshow("Original Image", img);
	namedWindow("Opened Image", WINDOW_NORMAL);
	imshow("Opened Image", opened);

	waitKey(0);
	destroyAllWindows();

	return 0;
}

运行结果

闭运算示例代码

#include "pch.h"

#include<iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

void closing(const Mat &src, Mat &dst, const Mat &kernel, int iterations)
{
	Mat temp;
	dilate(src, temp, kernel, Point(-1, -1), iterations);
	erode(temp, dst, kernel, Point(-1, -1), iterations);
}

int main(int argc, char** argv)
{
	//if (argc != 2) 
	//{
	//	cout << "Usage: ./Closing <Image Path>" << endl;
	//	return -1;
	//}

	// 加载图像
	Mat img = imread("666.png", IMREAD_GRAYSCALE);
	if (!img.data) 
	{
		cout << "Error opening image" << endl;
		return -1;
	}

	// 定义结构元素
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));

	// 初始化输出矩阵
	Mat closed;

	// 执行闭运算
	closing(img, closed, kernel, 1);

	// 显示结果
	namedWindow("Original Image", WINDOW_NORMAL);
	imshow("Original Image", img);
	namedWindow("Closed Image", WINDOW_NORMAL);
	imshow("Closed Image", closed);

	waitKey(0);
	destroyAllWindows();

	return 0;
}

运行结果

开运算

开运算(Opening)是形态学操作的一种组合形式,它通常用于去除图像中的小噪声点和细化图像中的物体边界。开运算首先对图像进行腐蚀(Erosion),然后再对腐蚀后的图像进行膨胀(Dilation)。

开运算原理

开运算的基本步骤如下:

1. 腐蚀:首先对输入图像进行一次腐蚀操作,这会缩小前景区域(通常为白色或非零值),去除小的噪声点。

2. 膨胀:接着对腐蚀后的图像进行一次膨胀操作,这会恢复因腐蚀而丢失的部分,但不会恢复被完全去除的小噪声点。

OpenCV中的开运算在OpenCV中,可以使用erode函数进行腐蚀操作,使用dilate函数进行膨胀操作。为了简化开运算的过程,OpenCV还提供了morphologyEx函数,可以直接执行开运算。

函数原型

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()
);

其中,op 参数可以设置为 MORPH_OPEN 来执行开运算。

参数说明
•src:输入图像。
•dst:输出图像,与输入图像具有相同的大小和类型。
•op:形态学操作类型,对于开运算为 MORPH_OPEN。
•kernel:结构元素,可以使用getStructuringElement函数生成。
•anchor:结构元素相对于原点的位置,默认为中心位置。
•iterations:迭代次数,默认为1次。
•borderType:边界处理类型,默认为BORDER_CONSTANT。
•borderValue:边界值,默认为morphologyDefaultBorderValue()。

示例代码

下面是一个使用OpenCV C++实现图像开运算的示例代码:

#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void opening(const Mat &src, Mat &dst, const Mat &kernel, int iterations) 
{
	morphologyEx(src, dst, MORPH_OPEN, kernel, Point(-1, -1), iterations);
}

int main(int argc, char** argv)
{
	/*if (argc != 2)
	{
		cout << "Usage: ./Opening <Image Path>" << endl;
		return -1;
	}*/

	// 加载图像
	Mat img = imread("888.png", IMREAD_GRAYSCALE);
	if (!img.data) 
	{
		cout << "Error opening image" << endl;
		return -1;
	}

	// 定义结构元素
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));

	// 初始化输出矩阵
	Mat opened;

	// 执行开运算
	opening(img, opened, kernel, 1);

	// 显示结果
	namedWindow("Original Image", WINDOW_NORMAL);
	imshow("Original Image", img);
	namedWindow("Opened Image", WINDOW_NORMAL);
	imshow("Opened Image", opened);

	waitKey(0);
	destroyAllWindows();

	return 0;
}


//代码解释
//1. 加载图像:使用 imread 函数以灰度模式加载图像。
//2. 定义结构元素:使用 getStructuringElement 函数生成一个3x3大小的矩形结构元素。
//3. 初始化输出矩阵:创建一个新的矩阵来存储开运算后的图像。
//4. 执行开运算:使用 morphologyEx 函数对图像进行开运算。
//5. 显示结果:使用 imshow 函数显示原始图像和开运算后的图像。
//
//注意事项
//•结构元素的形状:不同的结构元素形状会导致不同的开运算效果。矩形结构元素通常用于去除小的噪声点,而十字形结构元素则可能适合特定的应用场景。
//•迭代次数:增加迭代次数会使开运算效果更加明显,但过度的开运算可能会导致有用的信息丢失。
//•边界处理:开运算默认会处理图像的边界,可以选择不同的边界处理方式来影响开运算的效果。
//•数据类型:确保输出图像的数据类型与输入图像相同。
//
//应用场景
//•去噪:在二值化图像或边缘检测之后,可以使用开运算去除小的噪声点。
//•细化物体边界:开运算可以细化图像中的物体边界,使其更加平滑。
//•去除小的孔洞:开运算可以去除图像中的小孔洞,使前景区域更加连续。

运行结果

闭运算

闭运算(Closing)是形态学操作的一种组合形式,它通常用于连接接近的物体和填补物体内部的小孔洞。闭运算首先对图像进行膨胀(Dilation),然后再对膨胀后的图像进行腐蚀(Erosion)。

闭运算原理

闭运算的基本步骤如下:

1. 膨胀:首先对输入图像进行一次膨胀操作,这会扩大前景区域(通常为白色或非零值),填补物体内部的小孔洞。

2. 腐蚀:接着对膨胀后的图像进行一次腐蚀操作,这会恢复因膨胀而扩大的边界,但不会恢复物体内部的孔洞。

OpenCV中的闭运算

在OpenCV中,可以使用dilate函数进行膨胀操作,使用erode函数进行腐蚀操作。为了简化闭运算的过程,OpenCV还提供了morphologyEx函数,可以直接执行闭运算。

函数原型

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()
);
其中,op 参数可以设置为 MORPH_CLOSE 来执行闭运算。

参数说明
•src:输入图像。
•dst:输出图像,与输入图像具有相同的大小和类型。
•op:形态学操作类型,对于闭运算为 MORPH_CLOSE。
•kernel:结构元素,可以使用getStructuringElement函数生成。
•anchor:结构元素相对于原点的位置,默认为中心位置。
•iterations:迭代次数,默认为1次。
•borderType:边界处理类型,默认为BORDER_CONSTANT。
•borderValue:边界值,默认为morphologyDefaultBorderValue()。

示例代码

下面是一个使用OpenCV C++实现图像闭运算的示例代码:

#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void closing(const Mat &src, Mat &dst, const Mat &kernel, int iterations) 
{
	morphologyEx(src, dst, MORPH_CLOSE, kernel, Point(-1, -1), iterations);
}

int main(int argc, char** argv) 
{
	//if (argc != 2) 
	//{
	//	cout << "Usage: ./Closing <Image Path>" << endl;
	//	return -1;
	//}

	// 加载图像
	Mat img = imread("00.png", IMREAD_GRAYSCALE);
	if (!img.data) 
	{
		cout << "Error opening image" << endl;
		return -1;
	}

	// 定义结构元素
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));

	// 初始化输出矩阵
	Mat closed;

	// 执行闭运算
	closing(img, closed, kernel, 1);

	// 显示结果
	namedWindow("Original Image", WINDOW_NORMAL);
	imshow("Original Image", img);
	namedWindow("Closed Image", WINDOW_NORMAL);
	imshow("Closed Image", closed);

	waitKey(0);
	destroyAllWindows();

	return 0;
}

代码解释
1. 加载图像:使用 imread 函数以灰度模式加载图像。
2. 定义结构元素:使用 getStructuringElement 函数生成一个3x3大小的矩形结构元素。
3. 初始化输出矩阵:创建一个新的矩阵来存储闭运算后的图像。
4. 执行闭运算:使用 morphologyEx 函数对图像进行闭运算。
5. 显示结果:使用 imshow 函数显示原始图像和闭运算后的图像。

注意事项
•结构元素的形状:不同的结构元素形状会导致不同的闭运算效果。矩形结构元素通常用于填补物体内部的小孔洞,而十字形结构元素则可能适合特定的应用场景。
•迭代次数:增加迭代次数会使闭运算效果更加明显,但过度的闭运算可能会导致有用的信息丢失。
•边界处理:闭运算默认会处理图像的边界,可以选择不同的边界处理方式来影响闭运算的效果。•数据类型:确保输出图像的数据类型与输入图像相同。

应用场景
•连接接近的物体:闭运算可以连接彼此接近的物体,使其成为一个整体。
•填补物体内部的小孔洞:闭运算可以填补物体内部的小孔洞,使前景区域更加完整。
•平滑边界:闭运算可以平滑图像的边界,使其更加光滑。

运行结果

•顶帽变换:原图像减去开运算的结果,用于突出细节。

•黑帽变换:闭运算的结果减去原图像,用于突出阴影区域。

顶帽变换

顶帽变换(Top Hat Transformation)是形态学操作的一种形式,它主要用于增强图像中的细节和突出边缘或纹理特征。顶帽变换通过从原始图像中减去开运算(Opening)的结果来实现。

顶帽变换原理

顶帽变换的基本步骤如下:

1. 开运算:对输入图像进行一次开运算操作,这会去除小的噪声点和平滑边界。

2. 减法操作:将开运算的结果从原始图像中减去,得到的结果就是顶帽变换后的图像。

OpenCV中的顶帽变换

在OpenCV中,可以使用morphologyEx函数直接执行顶帽变换。

函数原型

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()
);
其中,op 参数可以设置为 MORPH_TOPHAT 来执行顶帽变换。
参数说明
•src:输入图像。
dst:输出图像,与输入图像具有相同的大小和类型。
•op:形态学操作类型,对于顶帽变换为 MORPH_TOPHAT。
•kernel:结构元素,可以使用getStructuringElement函数生成。
•anchor:结构元素相对于原点的位置,默认为中心位置。
iterations:迭代次数,默认为1次。
•borderType:边界处理类型,默认为BORDER_CONSTANT。
•borderValue:边界值,默认为morphologyDefaultBorderValue()。

示例代码

下面是一个使用OpenCV C++实现图像顶帽变换的示例代码:

#include "pch.h"

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void topHat(const Mat &src, Mat &dst, const Mat &kernel, int iterations) 
{
	morphologyEx(src, dst, MORPH_TOPHAT, kernel, Point(-1, -1), iterations);
}

int main(int argc, char** argv) 
{
	//if (argc != 2) 
	//{
	//	cout << "Usage: ./TopHat <Image Path>" << endl;
	//	return -1;
	//}

	// 加载图像
	Mat img = imread("81.png", IMREAD_GRAYSCALE);
	if (!img.data) 
	{
		cout << "Error opening image" << endl;
		return -1;
	}

	// 定义结构元素
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));

	// 初始化输出矩阵
	Mat tophat;

	// 执行顶帽变换
	topHat(img, tophat, kernel, 1);

	// 显示结果
	namedWindow("Original Image", WINDOW_NORMAL);
	imshow("Original Image", img);
	namedWindow("Top Hat Image", WINDOW_NORMAL);
	imshow("Top Hat Image", tophat);

	waitKey(0);
	destroyAllWindows();

	return 0;
}

代码解释
1. 加载图像:使用 imread 函数以灰度模式加载图像。
2. 定义结构元素:使用 getStructuringElement 函数生成一个3x3大小的矩形结构元素。
3. 初始化输出矩阵:创建一个新的矩阵来存储顶帽变换后的图像。
4. 执行顶帽变换:使用 morphologyEx 函数对图像进行顶帽变换。
5. 显示结果:使用 imshow 函数显示原始图像和顶帽变换后的图像。

注意事项
•结构元素的形状:不同的结构元素形状会导致不同的顶帽变换效果。矩形结构元素通常用于突出细节,而十字形结构元素则可能适合特定的应用场景。
•迭代次数:增加迭代次数会使顶帽变换效果更加明显,但过度的顶帽变换可能会导致有用的信息丢失。
•边界处理:顶帽变换默认会处理图像的边界,可以选择不同的边界处理方式来影响顶帽变换的效果。
•数据类型:确保输出图像的数据类型与输入图像相同。

应用场景
•增强细节:顶帽变换可以增强图像中的细节,突出边缘或纹理特征。
•突出噪声:顶帽变换可以突出图像中的小噪声点或细小特征。
•图像预处理:在进行后续图像处理之前,可以使用顶帽变换来增强图像中的重要特征。

运算结果

顶帽变换示例代码

#include "pch.h"

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void topHat(const Mat &src, Mat &dst, const Mat &kernel, int iterations) 
{
	morphologyEx(src, dst, MORPH_TOPHAT, kernel, Point(-1, -1), iterations);
}

int main(int argc, char** argv) 
{
	//if (argc != 2) 
	//{
	//	cout << "Usage: ./TopHat <Image Path>" << endl;
	//	return -1;
	//}

	// 加载图像
	Mat img = imread("81.png", IMREAD_GRAYSCALE);
	if (!img.data) 
	{
		cout << "Error opening image" << endl;
		return -1;
	}

	// 定义结构元素
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));

	// 初始化输出矩阵
	Mat tophat;

	// 执行顶帽变换
	topHat(img, tophat, kernel, 1);

	// 显示结果
	namedWindow("Original Image", WINDOW_NORMAL);
	imshow("Original Image", img);
	namedWindow("Top Hat Image", WINDOW_NORMAL);
	imshow("Top Hat Image", tophat);

	waitKey(0);
	destroyAllWindows();

	return 0;
}

运行结果

黑帽变换

黑帽变换(Black Hat Transformation)是形态学操作的一种形式,它主要用于突出图像中的阴影或低强度区域。黑帽变换通过从闭运算(Closing)的结果中减去原始图像来实现。

黑帽变换原理

黑帽变换的基本步骤如下:

1. 闭运算:对输入图像进行一次闭运算操作,这会连接接近的物体并填补物体内部的小孔洞。

2. 减法操作:将闭运算的结果减去原始图像,得到的结果就是黑帽变换后的图像。

黑帽变换的主要目的是突出那些比周围区域暗的小区域,即“暗斑”或“阴影”。

OpenCV中的黑帽变换

在OpenCV中,可以使用morphologyEx函数直接执行黑帽变换。

函数原型

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()
);

其中,op 参数可以设置为 MORPH_BLACKHAT 来执行黑帽变换。

参数说明
•src:输入图像。
•dst:输出图像,与输入图像具有相同的大小和类型。
•op:形态学操作类型,对于黑帽变换为 MORPH_BLACKHAT。
•kernel:结构元素,可以使用getStructuringElement函数生成。
•anchor:结构元素相对于原点的位置,默认为中心位置。
•iterations:迭代次数,默认为1次。
•borderType:边界处理类型,默认为BORDER_CONSTANT。
•borderValue:边界值,默认为morphologyDefaultBorderValue()。

示例代码

下面是一个使用OpenCV C++实现图像黑帽变换的示例代码:

#include "pch.h"

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void blackHat(const Mat &src, Mat &dst, const Mat &kernel, int iterations)
{
	morphologyEx(src, dst, MORPH_BLACKHAT, kernel, Point(-1, -1), iterations);
}

int main(int argc, char** argv) 
{
	/*if (argc != 2) 
	{
		cout << "Usage: ./BlackHat <Image Path>" << endl;
		return -1;
	}*/

	// 加载图像
	Mat img = imread("80.jpeg", IMREAD_GRAYSCALE);
	if (!img.data) 
	{
		cout << "Error opening image" << endl;
		return -1;
	}

	// 定义结构元素
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));

	// 初始化输出矩阵
	Mat blackhat;

	// 执行黑帽变换
	blackHat(img, blackhat, kernel, 1);

	// 显示结果
	namedWindow("Original Image", WINDOW_NORMAL);
	imshow("Original Image", img);
	namedWindow("Black Hat Image", WINDOW_NORMAL);
	imshow("Black Hat Image", blackhat);

	waitKey(0);
	destroyAllWindows();

	return 0;
}

代码解释
1. 加载图像:使用 imread 函数以灰度模式加载图像。
2. 定义结构元素:使用 getStructuringElement 函数生成一个3x3大小的矩形结构元素。
3. 初始化输出矩阵:创建一个新的矩阵来存储黑帽变换后的图像。
4. 执行黑帽变换:使用 morphologyEx 函数对图像进行黑帽变换。
5. 显示结果:使用 imshow 函数显示原始图像和黑帽变换后的图像。

注意事项
•结构元素的形状:不同的结构元素形状会导致不同的黑帽变换效果。矩形结构元素通常用于突出细节,而十字形结构元素则可能适合特定的应用场景。
•迭代次数:增加迭代次数会使黑帽变换效果更加明显,但过度的黑帽变换可能会导致有用的信息丢失。
•边界处理:黑帽变换默认会处理图像的边界,可以选择不同的边界处理方式来影响黑帽变换的效果。
•数据类型:确保输出图像的数据类型与输入图像相同。

应用场景
•突出阴影:黑帽变换可以突出图像中的阴影或低强度区域,这对于检测阴影或暗斑非常有用。
•增强对比度:黑帽变换可以帮助增强图像中的对比度,使得某些特征更加明显。
•图像预处理:在进行后续图像处理之前,可以使用黑帽变换来增强图像中的重要特征。

运行结果

通过黑帽变换,我们可以突出图像中的阴影或低强度区域。这种变换特别适用于:

•阴影检测:突出图像中的阴影部分。

•特征增强:增强图像中的关键特征,便于后续处理。

•去噪:去除图像中的小噪声点。

黑帽变换示例代码

#include "pch.h"

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void blackHat(const Mat &src, Mat &dst, const Mat &kernel, int iterations) 
{
	morphologyEx(src, dst, MORPH_BLACKHAT, kernel, Point(-1, -1), iterations);
}

int main(int argc, char** argv) 
{
	//if (argc != 2) 
	//{
	//	cout << "Usage: ./BlackHat <Image Path>" << endl;
	//	return -1;
	//}

	// 加载图像
	Mat img = imread("87.jpeg", IMREAD_GRAYSCALE);
	if (!img.data) 
	{
		cout << "Error opening image" << endl;
		return -1;
	}

	// 定义结构元素
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));

	// 初始化输出矩阵
	Mat blackhat;

	// 执行黑帽变换
	blackHat(img, blackhat, kernel, 1);

	// 显示结果
	namedWindow("Original Image", WINDOW_NORMAL);
	imshow("Original Image", img);
	namedWindow("Black Hat Image" ,WINDOW_NORMAL);
	imshow("Black Hat Image", blackhat);

	waitKey(0);
	destroyAllWindows();

	return 0;
}

运行结果

实验代码

// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>

using namespace cv;
//#pragma comment(lib, "opencv_world450d.lib")  //引用引入库 

/// 全局变量
Mat src, dst;

int morph_elem = 0;
int morph_size = 0;
int morph_operator = 0;
int const max_operator = 4;
int const max_elem = 2;
int const max_kernel_size = 21;

const char* window_name = "Morphology Transformations Demo";

void Morphology_Operations(int, void*);

/** @函数 main */
int main(int argc, char** argv)
{
	/// 装载图像
	src = imread("13.jpeg",IMREAD_COLOR);
	if (!src.data)
	{
		return -1;
	}

	/// 创建显示窗口
	namedWindow(window_name, WINDOW_NORMAL);

	/// 创建选择具体操作的 trackbar
	createTrackbar("Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat", window_name, &morph_operator, max_operator, Morphology_Operations);

	/// 创建选择内核形状的 trackbar
	createTrackbar("Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name,&morph_elem, max_elem,Morphology_Operations);

	/// 创建选择内核大小的 trackbar
	createTrackbar("Kernel size:\n 2n +1", window_name,&morph_size, max_kernel_size,Morphology_Operations);

	/// 启动使用默认值
	Morphology_Operations(0, 0);

	waitKey(0);
	return 0;
}

 
void Morphology_Operations(int, void*)
{
	// 由于 MORPH_X的取值范围是: 2,3,4,5 和 6
	int operation = morph_operator + 2;

	Mat element = getStructuringElement(morph_elem, Size(2 * morph_size + 1, 2 * morph_size + 1), Point(morph_size, morph_size));

	/// 运行指定形态学操作
	morphologyEx(src, dst, operation, element);
	imshow(window_name, dst);
}

运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值