opencv学习 --- 腐蚀与膨胀 putText()

一、先介绍几个API

(1)opencv中除了提供绘制各种图形的函数外,还提供了一个特殊的绘制函数——在图像上绘制文字。这个函数即是cv::putText()。

	void cv::putText(
		cv::Mat& img, // 待绘制的图像
		const string& text, // 待绘制的文字
		cv::Point origin, // 文本框的左下角
		int fontFace, // 字体 (如cv::FONT_HERSHEY_PLAIN)
		double fontScale, // 尺寸因子,值越大文字越大
		cv::Scalar color, // 线条的颜色(RGB)
		int thickness = 1, // 线条宽度
		int lineType = 8, // 线型(4邻域或8邻域,默认8邻域)
		bool bottomLeftOrigin = false // true='origin at lower left'
	);

opencv支持的文字字体有以下几种:

 另外,我们在实际绘制文字之前,还可以使用cv::getTextSize()接口先获取待绘制文本框的大小,以方便放置文本框。具体调用形式如下:

	cv::Size cv::getTextSize(
		const string& text,
		cv::Point origin,
		int fontFace,
		double fontScale,
		int thickness,
		int* baseLine
	);

下面就通过一个示例,来看看cv::getTextSize()与cv::putText()相结合的妙用:

	//创建空白图用于绘制文字
	cv::Mat image = cv::Mat::zeros(cv::Size(640, 480), CV_8UC3);
	//设置蓝色背景
	image.setTo(cv::Scalar(100, 0, 0));
 
	//设置绘制文本的相关参数
	std::string text = "Hello World!";
	int font_face = cv::FONT_HERSHEY_COMPLEX; 
	double font_scale = 2;
	int thickness = 2;
	int baseline;
	//获取文本框的长宽
	cv::Size text_size = cv::getTextSize(text, font_face, font_scale, thickness, &baseline);
 
	//将文本框居中绘制
	cv::Point origin; 
	origin.x = image.cols / 2 - text_size.width / 2;
	origin.y = image.rows / 2 + text_size.height / 2;
	cv::putText(image, text, origin, font_face, font_scale, cv::Scalar(0, 255, 255), thickness, 8, 0);
 
	//显示绘制解果
	cv::imshow("image", image);
	cv::waitKey(0);
	return 0;

绘制文字如下:

上方的介绍转载于 https://blog.csdn.net/guduruyu/article/details/68491211

(2)再介绍一个API createTrackbar
创建一个跟踪条(轨迹条),并将跟踪条附到制定的窗口上。
C++:

int createTrackbar(const string& trackbarname, const string& winname, int* value, int count, TrackbarCallback onChange=0, void* userdata=0)
参数:
trackbarname=》所创建的跟踪条的名字
winname=》跟踪条所依附的窗口的名字
value=》可选的指向整型变量的指针,整型变量的值对应于滑动条的位置。初始创建时,滑动条的值就是这个整型变量的值。
count=》滑动条最大的值。最小值总是为0。
onChange=》指向回调函数的指针,每次滚动条改变位置时,这个函数就会被调用。这个函数的原型应该为:void Foo(int, void*);其中第一个参数是跟踪条的位置,第二个参数是用户数据(见下一个参数)。如果回调为空,表示没有回调函数被调用,仅仅value会有变化。
userdata=》通过回调函数传递的用户数据(传递参数)。它可以控制跟踪条事件而不需要使用全局变量。
这个createTrackbar函数创建一个具有特定名称和范围的轨迹条(滚动条,或者说是滑块范围控制工具),指定一个和轨迹条位置同步的变量。而且要指定回调函数,在轨迹条位置改变的时候来调用这个回调函数。创建的轨迹条显示在指定的winname所代表的窗口上。

二、腐蚀与膨胀

我们在《初始滤波之均值滤波》中有聊过滤波的本质,以及介绍了其中一种线性滤波(均值滤波)。对于常见的非线性滤波“中值滤波”也在《视频的读取和处理》中有介绍。今天我们来介绍另外两种滤波方式:

  • 最大值滤波
  • 最小值滤波

再了解这两种滤波之前,我们先来看一些概念。

啥是形态学?

简单来讲,形态学操作就是基于形状的一系列图像处理操作。通过将结构元素作用于输入图像来产生输出图像。

有啥作用?

常用的形态学处理方法包括:腐蚀、膨胀、开运算、闭运算、顶帽运算、底帽运算,其中膨胀腐蚀是图像处理中最常用的形态学操作手段,其他方法是两者相互组合而产生的。

膨胀和腐蚀的运用广泛:

  • 消除噪声
  • 分割(isolate)独立的图像元素,以及连接(join)相邻的元素。
  • 寻找图像中的明显的极大值区域或极小值区域。
如何实现?

我们可以想象跟卷积类似,首先选取一个结构元素(我们以3*3的矩形核为例),并且定义其锚定点(以重心为例),结构元素覆盖的部分。

以结构元素的最小值填充锚定点的做法为腐蚀

以结构元素的最大值填充锚定点的做法为膨胀

是不是变相的滤波?

下面介绍 膨胀和腐蚀 中所用到的API

首先获取结构元素(获取滤波核):

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

 

  • shape:表示内核的形状,有三种形状可以选择。
    • 矩形:MORPH_RECT;
    • 交叉形:MORPH_CROSS;
    • 椭圆形:MORPH_ELLIPSE;
  • ksize 是指结构元素大小
  • anchor 中心锚点的位置     

腐蚀:

  • 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 输入图像,任意通道的
  • dst 输出图像,类型与通道数目必须跟输入保持一致
  • kernel 结构元素
  • anchor 中心位置锚定
  • iterations 循环次数
  • borderType 边缘填充类型(不用关心,使用默认值)

   

膨胀:

CV_EXPORTS_W void dilate( 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 输出图像,类型与通道数目必须跟输入保持一致
  • kernel 结构元素, 如果kernel=Mat()则为设定的3×3矩形。
  • anchor 锚定位置,默认中心位置。
  • iterations 循环次数
  • borderType 边缘填充类型(不用关心,使用默认值)

介绍转载于:https://zhuanlan.zhihu.com/p/83078037

代码:

// ExpansionCorrosion.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
Mat src,erosion_dst,dilation_dst;
int erosion_elem = 0;
int erosion_size = 0;
int dilation_elem = 0;
int dilation_size = 0;

int const  max_elem = 2;
int const max_kernel_size = 21;
char text[] = "Element: 0:Rect 1:Coss 2:Ellipse";

void Erosion(int ,void*)
{
	int erosion_type = 0;
	if (erosion_elem == 0) {
		erosion_type = MORPH_RECT;       // 创建的核形状,矩形
	}
	if (erosion_elem == 1) {
		erosion_type = MORPH_CROSS;      // 十字形
	}
	if (erosion_elem == 2) {
		erosion_type = MORPH_ELLIPSE;    // 椭圆
	}
	// 返回构造性元素。
	Mat element = getStructuringElement(erosion_type, Size(2 * erosion_size + 1, 2 * erosion_size + 1), Point(erosion_size, erosion_size));
	// 腐蚀
	erode(src, erosion_dst, element);

	Point textOrg(100,250);
	// 在图像上绘制文字,erosion_dst是待绘制的图像,text 绘制文本,textOrg 绘制文本框的左下角位置
	//FONT_HERSHEY_COMPLEX 字体,1 为字体大小,Scalar(255,0,255) 为颜色,2 为字体粗细,4: 线型(4邻域或8邻域,默认8邻域)
	putText(erosion_dst, text, textOrg, FONT_HERSHEY_COMPLEX, 1, Scalar(255,0,255), 1);   
	imshow("腐蚀", erosion_dst);
	
}

void Dilate(int, void*)
{
	int dilation_type = 0;
	if (dilation_elem == 0){
		dilation_type = MORPH_RECT;
	}
	else if (dilation_elem == 1){
		dilation_type = MORPH_CROSS;
	}
	else if (dilation_elem == 2) {
		dilation_type = MORPH_ELLIPSE;
	}
	Mat element = getStructuringElement(dilation_type, Size(2 * dilation_size + 1, 2 * dilation_size + 1), Point(dilation_size, dilation_size));
	//膨胀
	dilate(src, dilation_dst, element);

	Point textOrg(100, 250);
	putText(dilation_dst, text, textOrg, FONT_HERSHEY_COMPLEX, 1, Scalar(255, 0, 255), 2, 4);
	imshow("膨胀", dilation_dst);
}

int main()
{
	src = imread("C:\\Users\\Geek\\Desktop\\1281425_2019-07-18_10_0\\6232.bmp");
	if (src.empty())
		return 0;
	namedWindow("腐蚀", WINDOW_AUTOSIZE);

	createTrackbar("Element:", "腐蚀", &erosion_elem, max_elem, Erosion);
	createTrackbar("kernel:","腐蚀", &erosion_size, max_kernel_size, Erosion);
	// 一定要注意参数
	namedWindow("膨胀", WINDOW_AUTOSIZE);
	createTrackbar("Element:", "膨胀", &dilation_elem, max_elem, Dilate);
	createTrackbar("kernel:", "膨胀", &dilation_size, max_kernel_size, Dilate);

	Erosion(0,0);
	Dilate(0, 0);
	waitKey(0);
    return 0;

}

不知道为什么滑动条kernel 只能4个单位4个单位的滑,谁能解答一下???

                                                                                                                                             

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值