1,图像形态学介绍
形态学的应用: 主要针对二值图进行,消除噪声、边界提取、区域填充、连通分量提取、凸壳、细化、粗化等;分割出独立的图像元素,或者图像中相邻的元素;求取图像中明显的极大值区域和极小值区域;求取图像梯度。
2,结构和元素形状
膨胀和腐蚀操作的核心内容是结构元素,(后面的开闭运算等重要的也是结构元素的设计,一个合适的结构元素的设计可以带来很好的处理效果)一般来说结构元素是由元素为1或者0的矩阵组成。结构元素为1的区域定义了图像的领域,领域内的像素在进行膨胀和腐蚀等形态学操作时要进行考虑。
一般来说,二维或者平面结构的结构元素要比处理的图像小得多。结构元素的中心像素,即结构元素的原点,与输入图像中感兴趣的像素值(即要处理的像素值)相对应。三维的结构元素使用0和1来定义x-y平面中结构元素的范围,使用高度值定义第三维。
CV_EXPORTS_W Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));
//shape: \MORPH_CROSS(十字交叉形核) \MORPH_ELLIPSE(椭圆形核));
// ksize: 结构元素大小;
// anchor: 锚点 默认是Point(-1, -1)意思就是中心像素,也可以自己指定
//结构元素设计
Mat elementRect, elementCross, elementEllipse;
elementRect = getStructuringElement(MORPH_RECT, cv::Size(3, 3), cv::Point(-1, -1));//矩形
elementCross = getStructuringElement(MORPH_CROSS, cv::Size(3, 3), cv::Point(-1, -1));//十字
elementEllipse = getStructuringElement(MORPH_ELLIPSE, cv::Size(5, 5), cv::Point(-1, -1));//椭圆
cout << "3X3矩形核:" << endl << elementRect << endl;
cout << "3X3十字交叉形核:" << endl << elementCross << endl;
cout << "5X5椭圆形核:" << endl << elementEllipse << endl << endl;
3,腐蚀和膨胀
膨胀
膨胀操作是形态学中另外一种基本的操作。膨胀操作和腐蚀操作的作用是相反的,膨胀操作能对图像的边界进行扩张。膨胀操作将与当前对象(前景)接触到的背景点合并到当前对象内,从而实现将图像的边界点向外扩张。
如果图像内两个对象的距离较近,那么在膨胀的过程中,两个对象可能会连通在一起。膨胀操作对填补图像分割后图像内所存在的空白相当有帮助。二值图像的膨胀示例如图所示。
膨胀使图像中的白色高亮部分进行膨胀,“邻域扩张”,膨胀效果拥有比原图更大的高亮区域,可以填补图像缺陷,用来扩充边缘或填充小的孔洞,也可以用来连接两个分开的物体。
膨胀的原理是求局部最大值的操作,将 1 值扩充到邻近像素,从而扩大白色值范围、压缩黑色值范围。
用卷积来描述膨胀操作,中心为 1、其它为 0 的卷积核沿着图像滑动卷积,与卷积核对应的原图像的像素值中只要有一个为 1, 则图像的中心元素的像素值为 1,否则(全 0)为 0。
用卷积来描述膨胀操作,结构元素 B 是中心为 1、其它为 0 的卷积模板(核):
(1)卷积核 B 沿着图像滑动,扫描图像 A 的每一个像素;
(2)用结构元素与其覆盖的二值图像进行 “与操作”;
(3)如果图像与卷积核对应区域的所有像素值都是 0,则图像的该像素值仍为 0;否则为 1。
在去噪声时通常先进行腐蚀,在去掉白噪声的同时,使前景对象变小;然后再对进行膨胀,此时噪声已经被去除,可以增加前景。
void dilate(
InputArray src,//输入图像,即源图像,填Mat类的对象即可。图像通道的数量可以是任意的,但图像深度应为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之一
OutputArray dst,//目标图像,需要和源图片有一样的尺寸和类型
InputArray kernel,//操作的核。若为NULL时,表示的是使用参考点位于中心3x3的核,可以使用getStructuringElement来创建结构元素
Point anchor=Point(-1,-1),//锚点的位置,其有默认值(-1,-1),表示锚位于中心
int iterations=1,//迭代使用该函数的次数,默认值为1
int borderType=BORDER_CONSTANT,//用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT
const Scalar& borderValue=morphologyDefaultBorderValue() //当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档中的createMorphologyFilter()函数得到更详细的解释
);
//使用dilate函数时,一般我们只需要填前面的三个参数,后面的四个参数都有默认值。而且往往结合getStructuringElement一起使用。
参数说明:
src:输入图像,可以为单通道或多通道,图像深度必须为 CV_8U, CV_16U, CV_16S, CV_32F 或 CV_64F
dst:输出图像,大小和类型与 src 相同
kernel:结构元(卷积核),null 时使用 3*3 矩形卷积核
anchor:卷积核的锚点位置,默认值 (-1, -1) 表示以卷积核的中心为锚点
iterations:应用膨胀的次数,可选项,默认值为 1
borderType:边界扩充的类型
borderValue:当 borderType=BORDER_CONSTANT 时以常量 value 填充扩充边界,默认值为 (0,0,0)
注意事项:
函数支持就地模式,腐蚀操作可以迭加使用多次。
在多通道图像的情况下,每个通道独立处理 。
腐蚀
腐蚀和膨胀是图像处理中最基本的形态学操作,是很多高级处理方法的基础。
腐蚀和膨胀是对白色部分(高亮部分)而言的,膨胀就是图像中的高亮部分进行膨胀,腐蚀就是原图中的高亮部分被腐蚀。
腐蚀使图像中白色高亮部分被腐蚀,“邻域被蚕食”,腐蚀的效果拥有比原图更小的高亮区域,可以去掉毛刺,去掉孤立的像素,提取骨干信息。
腐蚀的原理是求局部最小值的操作,将 0 值扩充到邻近像素,从而扩大黑色值范围、压缩白色值范围。
腐蚀是最基本的形态学操作之一,它能够将图像的边界点消除,使图像沿着边界向内收缩,也可以将小于指定结构体元素的部分去除。腐蚀用来“收缩”或者“细化”二值图像中的前景,借此实现去除噪声、元素分割等功能。例如,在图中,左图是原始图像,右图是对其腐蚀的处理结果。
腐蚀的具体操作:用一个结构元素(一般是3×3的大小)扫描图像中的每一个像素,用结构元素中的每一个像素与其覆盖的像素做“与”操作,如果都为1,则该像素为1,否则为0。用最小值来替换中心像素
腐蚀的作用:是消除物体边界点,使目标缩小,可以消除小于结构元素的噪声点;腐蚀了就意味着图像中物体的边界被侵蚀了,轮廓向内收缩,体积变小了。
CV_EXPORTS_W void erode( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
参数说明:
src:输入图像,可以为单通道或多通道,图像深度必须为 CV_8U, CV_16U, CV_16S, CV_32F 或 CV_64F
dst:输出图像,大小和类型与 src 相同
kernel:结构元(卷积核),null 时使用 3*3 矩形结构元素
anchor:卷积核的锚点位置,默认值 (-1, -1) 表示以卷积核的中心为锚点
iterations:应用腐蚀操作的次数,可选项,默认值为 1
borderType:边界扩充的类型
borderValue:当 borderType=BORDER_CONSTANT 时以常量 value 填充扩充边界,默认值为 (0,0,0)
注意事项:
函数支持就地模式,腐蚀操作可以迭加使用多次。
在多通道图像的情况下,每个通道独立处理 。
参考示例
Mat src = imread("F:/code/images/hist_02.jpg");
namedWindow("input", WINDOW_AUTOSIZE);
imshow("input", src);
//二值图
Mat gray, binary;
cvtColor(src, gray, COLOR_BGR2GRAY);
threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
namedWindow("binary", WINDOW_AUTOSIZE);
imshow("binary", binary);
//腐蚀
Mat elementRect = getStructuringElement(MORPH_RECT, cv::Size(3, 3), cv::Point(-1, -1));//矩形
erode(binary, binary, elementRect);
namedWindow("erode", WINDOW_AUTOSIZE);
imshow("erode", binary);
//膨胀
Mat elementRect2 = getStructuringElement(MORPH_RECT, cv::Size(3, 3), cv::Point(-1, -1));//矩形
dilate(binary, binary, elementRect2);
namedWindow("dilate", WINDOW_AUTOSIZE);
imshow("dilate", src);
4,开闭操作
开操作- open
先腐蚀后膨胀
可以去掉小的对象,假设对象是前景色,背景是黑色
用于移除一些小物体(假设图像中物体是亮的,背景是暗的)。如下图所示,左侧是原始图像,上面有一些小亮斑。在进行开运算之后,去掉了斑点。
闭操作-close
先膨胀后腐蚀(bin2)
可以填充小的洞(fill hole),假设对象是前景色,背景是黑色
用于移除一些小的孔洞(图像中较亮目标中的暗点)
CV_EXPORTS_W void morphologyEx( InputArray src, OutputArray dst,
int op, //操作的类型:MORPH_ERODE = 0, //腐蚀
MORPH_DILATE = 1, //膨胀
MORPH_OPEN = 2, //开操作
MORPH_CLOSE = 3, //闭操作
MORPH_GRADIENT = 4, //梯度操作
MORPH_TOPHAT = 5, //顶帽操作
MORPH_BLACKHAT = 6, //黑帽操作
MORPH_HITMISS = 7
InputArray kernel,//结构元素
Point anchor = Point(-1,-1), //锚点
int iterations = 1,//迭代使用函数的次数
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
参数说明:
src:输入图像,可以为单通道或多通道,图像深度必须为 CV_8U, CV_16U, CV_16S, CV_32F 或 CV_64F
dst:输出图像,大小和类型与 src 相同
op:形态学运算类型
cv.MORPH_ERODE:腐蚀
cv.MORPH_DILATE:膨胀
cv.MORPH_OPEN:开运算, 先腐蚀再膨胀
cv.MORPH_CLOSE:闭运算, 先膨胀再腐蚀
cv.MORPH_GRADIENT:形态学梯度, 膨胀图与腐蚀图之差
cv.MORPH_TOPHAT:顶帽变换, 原图像与开运算之差
cv.MORPH_BLACKHAT:黑帽变换, 闭运算图与原图像之差
cv.MORPH_HITMISS: 击中击不中运算
kernel:结构元(卷积核),null 时使用 3*3 矩形卷积核
anchor:卷积核的锚点位置,负值表示以卷积核的中心为锚点
iterations:应用腐蚀和膨胀的次数,可选项,默认值为 1
borderType:边界扩充的类型
borderValue:当 borderType=BORDER_CONSTANT 时以常量 value 填充扩充边界,默认值为 (0,0,0)
注意事项:
函数支持就地模式,开运算操作可以迭加使用多次。
迭代次数是应用腐蚀和膨胀操作的次数,注意两次迭代的开操作相当于应用“腐蚀→腐蚀→膨胀→膨胀”,而不是“腐蚀→膨胀→腐蚀→膨胀”。
示例
Mat src = imread("F:/code/images/cells.png");
CV_Assert(!src.empty());
Mat gray, binary;
cvtColor(src, gray, COLOR_BGR2GRAY);
threshold(gray, binary, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
bitwise_not(binary, binary, Mat());
imshow("binary", binary);
//开操作
Mat dst;
Mat kernel = getStructuringElement(MORPH_RECT, Size(7, 7), Point(-1, -1));//Size(15,1)为水平方向结构元素 Size(1, 15)为垂直方向结构元素
morphologyEx(binary, dst, MORPH_OPEN, kernel, Point(-1, -1), 1);
imshow("open-demo", dst);
//闭操作
Mat dst2;
Mat kerne2 = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));
morphologyEx(binary, dst2, MORPH_CLOSE, kerne2, Point(-1, -1), 1);
imshow("close-demo", dst2);
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/182009.html