opencv学习 - 图像处理 形态学操作 开操作、闭操作、形态学梯度、顶帽和黑帽

膨胀、腐蚀、开、闭运算是形态学操作中最基本的操作

形态学操作一般针对于 二值化图像。

腐蚀:在核区域内,选择最小像素值为当前像素值,和最小值滤波类似、不同点:腐蚀的核形状可以是圆形、矩形和十字形等等。腐蚀从图像变化上来看:就是黑吃白(因为选择的是最小值像素值)。

膨胀:在核区域内,选择最大像素值为当前像素值,和最大值滤波类似;不同点:同上,膨胀从图像变化上来看:白吃黑(因选最大像素值)。

开运算:先腐蚀,后膨胀   应用:如 去掉在黑色背景下小块白色区域, 先腐蚀:把小块白色区域吃掉。后膨胀:把大块白色复原。

闭运算:先膨胀,后腐蚀   应用:如 去掉在白色背景下的小块黑色区域。

形态渐层处理:膨胀 减去 腐蚀  又称:基本梯度。还有内部梯度(原图 - 腐蚀图)、方向梯度(x或y方向进行梯度计算)。

顶帽:原图 与 开运算的差值            ---得开运算后的图与原图的变化图。 如:开运算解释 应用中的 小块白色区域。

黑帽:闭运算 与 原图的差值。         ---得闭运算后的图与原图的变化图。如:开运算解释 应用中的 小块黑色区域。

根据想要去掉的区域大小,进行选择核大小。

 

介绍两个个API

(1)自适应阈值化操作:adaptiveThreshold()函数

1. 每个像素位置处的二值化阈值不是固定不变的,而是由其周围邻域像素的分布来决定的。

2. 亮度较高的图像区域的二值化阈值通常会较高,而亮度低的图像区域的二值化阈值则会相适应的变小。

3. 不同亮度、对比度、纹理的局部图像区域将会拥有相对应的局部二值化阈值。

1.    void adaptiveThreshold(InputArray src, OutputArray dst,  
2.                           double maxValue, int adaptiveMethod,  
3.                           int thresholdType, int bolckSize, double C)  

参数说明

参数1:InputArray类型的src,输入图像,填单通道,单8位浮点类型Mat即可。
参数2:函数运算后的结果存放在这。即为输出图像(与输入图像同样的尺寸和类型)。
参数3:预设满足条件的最大值。
参数4:指定自适应阈值算法。可选择ADAPTIVE_THRESH_MEAN_C 或 ADAPTIVE_THRESH_GAUSSIAN_C两种。(具体见下面的解释)。
参数5:指定阈值类型。可选择THRESH_BINARY或者THRESH_BINARY_INV两种。(即二进制阈值或反二进制阈值)。
参数6:表示邻域块大小,用来计算区域阈值,一般选择为3、5、7......等。
参数7:参数C表示与算法有关的参数,它是一个从均值或加权均值提取的常数,可以是负数。(具体见下面的解释)。

对参数4与参数7内容的解释:

自适应阈值化计算大概过程是为每一个象素点单独计算的阈值,即每个像素点的阈值都是不同的,就是将该像素点周围B*B区域内的像素加权平均,然后减去一个常数C,从而得到该点的阈值。B由参数6指定,常数C由参数7指定。

ADAPTIVE_THRESH_MEAN_C,为局部邻域块的平均值,该算法是先求出块中的均值,再减去常数C。

ADAPTIVE_THRESH_GAUSSIAN_C,为局部邻域块的高斯加权和。该算法是在区域中(x, y)周围的像素根据高斯函数按照他们离中心点的距离进行加权计算,再减去常数C。

举个例子:如果使用平均值方法,平均值mean为190,差值delta(即常数C)为30。那么灰度小于160的像素为0,大于等于160的像素为255。如下图:

如果是反向二值化,如下图:

delta(常数C)选择负值也是可以的。

(2)高级形态变换函数  morphologyEx

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

morphologyEx函数利用基本的膨胀和腐蚀技术,来执行更加高级形态学变换
src
输入图像,图像位深应该为以下五种之一:CV_8U, CV_16U,CV_16S, CV_32F 或CV_64F。
dst
输出图像,需和源图片保持一样的尺寸和类型。
op
表示形态学运算的类型:
MORPH_OPEN – 开运算(Opening operation)
MORPH_CLOSE – 闭运算(Closing operation)
MORPH_GRADIENT - 形态学梯度(Morphological gradient)
MORPH_TOPHAT - 顶帽(Top hat)
MORPH_BLACKHAT - 黑帽(Black hat)
kernel
形态学运算的内核。为NULL,使用参考点位于中心3x3的核。一般使用函数getStructuringElement配合这个参数的使用,
kernel参数填保存getStructuringElement返回值的Mat类型变量。
anchor
锚的位置,其有默认值(-1,-1),表示锚位于中心。
iterations
迭代使用函数的次数,默认值为1。
borderType
用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_CONSTANT。
borderValue
当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),

一般我们不用去管他。需要用到它时,可以看官方文档中的createMorphologyFilter()函数得到更详细的解释。


提取线 和 提取ABCD 实例代码


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

using namespace std;
using namespace cv;

void MorV()        // 垂直线提取
{
	Mat src, dst,gray_src;
	src = imread("C:/Users/Geek/Desktop/1281425_2019-07-18_10_0/zhiline.png", 1);
	imshow("src", src);
	cvtColor(src,gray_src,CV_BGR2GRAY);
	imshow("gray_src", gray_src);
	Mat BinImage;
	//imshow("~gray_src",~gray_src);

	adaptiveThreshold(gray_src, BinImage, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 21, 25);
	// 一定要学习好使用这个函数,注意各个参数,其实可以自己写(看我博客即可)

	imshow("BinImage", BinImage);
	// 水平核
	Mat hline = getStructuringElement(MORPH_RECT, Size(30, 1), Point(-1, -1));
	// 竖直核
	Mat vline = getStructuringElement(MORPH_RECT, Size(1, 40), Point(-1, -1));   // 你看我垂直核多大,因为A太粗了
	Mat DImage;

	//dilate(BinImage, DImage, hline);   // 膨胀
	//erode(DImage, dst, hline);      // 腐蚀
	morphologyEx(BinImage,dst,MORPH_CLOSE, vline, Point(-1, -1));

	blur(dst, dst, Size(3, 3),Point(-1,-1));
	
	imshow("dst",dst);
	waitKey(0);
}

void MorH()   // 水平线提取
{
	Mat src, dst, gray_src;
	src = imread("C:/Users/Geek/Desktop/1281425_2019-07-18_10_0/zhiline.png", 1);
	imshow("src", src);
	cvtColor(src, gray_src, CV_BGR2GRAY);
	imshow("gray_src", gray_src);
	Mat BinImage;
	//imshow("~gray_src",~gray_src);

	adaptiveThreshold(~gray_src, BinImage, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 21, -10);
	// 看准 ~ 和 21窗口大小 和  阈值减去的值(最后一个值)。 
	// 一定要学习好使用这个函数,注意各个参数,其实可以自己写(看我博客即可)

	imshow("BinImage", BinImage);
	// 水平核
	Mat hline = getStructuringElement(MORPH_RECT, Size(20, 1), Point(-1, -1));
	// 竖直核
	Mat vline = getStructuringElement(MORPH_RECT, Size(1, 20), Point(-1, -1));
	Mat DImage;

	//erode(BinImage, DImage, hline);   // 腐蚀
	//dilate(DImage, dst, hline);      // 膨胀
	morphologyEx(BinImage, dst, MORPH_OPEN, hline, Point(-1, -1));   // 开运算

	bitwise_not(dst, dst);   // 进行 非运算 和 ~应该相同。
	blur(dst, dst, Size(3, 3), Point(-1, -1));

	imshow("dst", dst);
	waitKey(0);
}

void MorABCD()    // 提取ABCD
{
	Mat src, dst, gray_src;
	src = imread("C:/Users/Geek/Desktop/1281425_2019-07-18_10_0/处理ABCD.png", 1);
	imshow("src", src);
	cvtColor(src, gray_src, CV_BGR2GRAY);
	imshow("gray_src", gray_src);
	Mat BinImage;
	//imshow("~gray_src",~gray_src);

	adaptiveThreshold(~gray_src, BinImage, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 21, -10);
	// 看准 ~ 和 21窗口大小 和  阈值减去的值(最后一个值)。 
	// 一定要学习好使用这个函数,注意各个参数,其实可以自己写(看我博客即可)

	imshow("BinImage", BinImage);
	// 水平核
	Mat hline = getStructuringElement(MORPH_RECT, Size(20, 1), Point(-1, -1));
	// 竖直核
	Mat vline = getStructuringElement(MORPH_RECT, Size(1, 20), Point(-1, -1));
	Mat ABCD = getStructuringElement(MORPH_RECT, Size(2, 2), Point(-1, -1));
	Mat DImage;

	//erode(BinImage, DImage, hline);   // 腐蚀
	//dilate(DImage, dst, hline);      // 膨胀
	morphologyEx(BinImage, dst, MORPH_OPEN, ABCD, Point(-1, -1));   // 开运算
	//morphologyEx(BinImage, dst, MORPH_OPEN, ABCD, Point(-1, -1));   // 开运算
    blur(dst, dst, Size(3, 3), Point(-1, -1));
	bitwise_not(dst, dst);   // 进行 非运算 和 ~应该相同。	

	imshow("dst", dst);
	waitKey(0);
}
int main()
{
	MorV();
	MorH();
	MorABCD();
    return 0;
}

结果:

提取ABCD

提取直线结果

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值