数字图像处理 图像形态学变换

前言

形态学图像处理(简称形态学)是指一系列处理图像形状特征的图像处理技术。形态学的基本思想是利用一种特殊的结构元来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别。它的主要思想是集合论,处理的图像是二值图像,其中1表示前景(白色部分),0表示背景(黑色部分)。

图像形态学主要有腐蚀、膨胀、开操作以及闭操作。介绍这些概念之前,先了解一个基本概念:结构元。结构元(Structuring Elements,SE)可以是任意形状,SE中的的值可以是0或1。常见的结构元有矩形和十字形。结构元有一个锚点O,O一般定义为结构元的中心(也可以自由定义位置)。如下图所示是几个不同形状的结构元,紫红色区域为锚点O。
在这里插入图片描述

膨胀

膨胀(dilate)是对图像高亮部分进行“领域扩张”,领域扩张,效果图拥有比原图更大的高亮区域。根据《数字图像处理》一书的说明,将结构元 s s s在图像 f f f上滑动,把结构元锚点位置的图像像素点的灰度值设置为结构元值为1的区域对应图像区域像素的最大值。用公式表示如下,其中element为结构元,(x,y)为锚点O的位置,x’和y’为结构元值为1的像素相对锚点O的位置偏移,src表示原图,dst表示结果图。
在这里插入图片描述

在这里插入图片描述

实现

C++实现:

#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("./morphologyEx.jpg");
	cout << img.size() << endl;
	imshow("原图", img);
	Mat dst;
	//获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
	//形态学膨胀
	dilate(img, dst, element);
	imshow("形态学开操作", dst);
	waitKey();
	return 0;
}

python实现:


import cv2
import numpy as np 
img = cv2.imread('j.png',0)
# 读入彩色图像或灰度图的话需要对图像进行二值化
kernel = np.ones((5,5),np.uint8)  
result = cv2.dilate(img,kernel,iterations = 1)

腐蚀

腐蚀(erode)是原图中的高亮区域被蚕食,领域缩减,效果图拥有比原图更小的高亮区域。将结构元 s s s在图像 f f f上滑动,把结构元锚点位置的图像像素点的灰度值设置为结构元值为1的区域对应图像区域像素的最小值。用公式表示如下,其中element为结构元,(x,y)为锚点O的位置,x’和y’为结构元值为1的像素相对锚点O的位置偏移,src表示原图,dst表示结果图。
在这里插入图片描述

实现

C++实现:

#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("./morphologyEx.jpg");
	cout << img.size() << endl;
	imshow("原图", img);
	Mat dst;
	//获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
	//形态学膨胀
	erode(img, dst, element);
	imshow("形态学开操作", dst);
	waitKey();
	return 0;
}

python实现:


import cv2
import numpy as np 
img = cv2.imread('j.png',0)
# 读入彩色图像或灰度图的话需要对图像进行二值化
kernel = np.ones((5,5),np.uint8)  
result= cv2.erode(img,kernel,iterations = 1)

开运算与闭运算

有了膨胀与腐蚀的基础后,开运算即先进行腐蚀操作然后进行膨胀操作,而闭运算则先进行膨胀操作后进行腐蚀操作。

开运算

开运算具有消除细小物体(噪声),在纤细处分离物体和平滑较大物体边界的作用。
在这里插入图片描述

实现

C++实现:

#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("./morphologyEx.jpg");
	cout << img.size() << endl;
	imshow("原图", img);
	Mat dst;
	//获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
	morphologyEx(img, dst, MORPH_OPEN, element);
	imshow("形态学开操作", dst);
	waitKey();
	return 0;
}

在里面有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()
)

参数如下:

  1. src:源图像Mat对象
  2. dst:目标图像Mat对象
  3. op:操作的类型。
enum MorphTypes{
    MORPH_ERODE    = 0, //腐蚀
    MORPH_DILATE   = 1, //膨胀
    MORPH_OPEN     = 2, //开操作
    MORPH_CLOSE    = 3, //闭操作
    MORPH_GRADIENT = 4, //梯度操作
    MORPH_TOPHAT   = 5, //顶帽操作
    MORPH_BLACKHAT = 6, //黑帽操作
    MORPH_HITMISS  = 7  
};
  1. kernel:用于膨胀操作的结构元素,如果取值为Mat(),那么默认使用一个3 x 3 的方形结构元素,可以使用getStructuringElement()来创建结构元素
  2. anchor:参考点,其默认值为(-1,-1)说明位于kernel的中心位置。
  3. borderType:边缘类型,默认为BORDER_CONSTANT。
  4. borderValue:边缘值,用它的默认值即可。

python实现:


import cv2
import numpy as np 
img = cv2.imread('j.png',0)
# 读入彩色图像或灰度图的话需要对图像进行二值化
kernel = np.ones((5,5),np.uint8)  
result= cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

cv2.morphologyEx参数说明:

  1. MORPH_OPEN:开运算
  2. MORPH_CLOSE:闭运算
  3. MORPH_GRADIENT:形态学梯度
  4. MORPH_TOPHAT:顶帽
  5. MORPH_BLACKHAT:黑帽
  6. MORPH_ERODE:腐蚀
  7. MORPH_DILATE:膨胀

闭运算

闭运算具有填充物体内细小空洞,连接邻近物体和平滑边界的作用。具体实现与开运算相反,这里不做展开了。

梯度运算

形态学梯度操作能描述图像亮度变化的剧烈程度;当想要突出高亮区域的外围时,则可以选用形态学梯度来突出边缘,可以保留物体的边缘轮廓。

#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("./morphologyEx.jpg");
	cout << img.size() << endl;
	imshow("原图", img);
	Mat dst;
	//获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
	//形态学梯度运算
	morphologyEx(img, dst, MORPH_GRADIENT, element);
	imshow("形态学梯度运算", dst);
	waitKey();
	return 0;
}

礼/顶帽

顶帽是原图与原图的开运算的差值图像。开运算放大了裂缝或者局部低亮度的区域,所以,从原图中减去开运算后的图,得到的结果突出了比原图轮廓周围的区域更明亮的区域,这个操作与选择的核的大小有关。TopHat运算一般用来分离比邻近点亮一些的斑块,可以使用这个运算提取背景。

#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("./morphologyEx.jpg");
	cout << img.size() << endl;
	imshow("原图", img);
	Mat dst,dst_open;
	// 获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	// 形态学礼帽
	morphologyEx(img, dst_open, MORPH_OPEN, element);
	morphologyEx(img, dst, MORPH_TOPHAT, element);
	imshow("开运算", dst_open);
	imshow("形态学礼帽", dst);
	waitKey();
	return 0;
}

python实现:

import cv2  
import numpy as np  
  
  
img = cv2.imread('credit_card_.png')  
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(21,21))  
tophat = cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,kernel)  
threshold = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV|  
                          cv2.THRESH_OTSU)[1]  
cv2.imshow("img",img)  
cv2.imshow("thres",threshold)  
cv2.waitKey(0)  
cv2.destroyAllWindows() 

黑帽

黑帽是闭运算结果与原图的差值图像。黑帽运算的结果突出了比原图轮廓周围的区域更暗的区域,且与选择的卷积核大小有关,所以黑帽运算用来分离比邻近点暗一些的斑块,效果图有非常完美的轮廓。

#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("./morphologyEx.jpg");
	cout << img.size() << endl;
	imshow("原图", img);
	Mat dst, dst_close;
	// 获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	// 形态学黑帽
	morphologyEx(img, dst_close, MORPH_CLOSE, element);
	morphologyEx(img, dst, MORPH_BLACKHAT, element);
	imshow("闭运算", dst_close);
	imshow("形态学黑帽", dst);
	waitKey();
	return 0;
}

python实现:

import cv2  
import numpy as np  
  
  
img = cv2.imread('close.jpg')  
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))  
tophat = cv2.morphologyEx(gray,cv2.MORPH_GRADIENT,kernel)  
cv2.imshow("img",img)  
cv2.imshow("thres",tophat)  
cv2.waitKey(0)  
cv2.destroyAllWindows() 

总结

  1. 膨胀(dilate)是对图像高亮部分进行“领域扩张”,领域扩张,效果图拥有比原图更大的高亮区域;
  2. 腐蚀(erode)是原图中的高亮区域被蚕食,领域缩减,效果图拥有比原图更小的高亮区域。
  3. 开运算:先腐蚀再膨胀,用来消除小物体
  4. 闭运算:先膨胀再腐蚀,用于排除小型黑洞
  5. 形态学梯度:就是膨胀图与腐蚀图之差,用于保留物体的边缘轮廓。
  6. 顶帽:原图像与开运算图之差,用于分离比邻近点亮一些的斑块。
  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值