C++图像的形态学操作

news2025/2/2 0:43:01

什么是图像的形态学操作?

    使用数学形态学的基本运算,由计算机对图像进行分析,以达到所需结果的一种技术。
形态学,morphology, 形态学最初是生物学中研究动物和植物结构的一个分支,被引入图像处理领域后,图像形态学就指以形态为基础对图像进行分析的一种方法或技术。

图像形态学操作的基本思想 :

    是用具有一定形态的结构元素去度量和提取图像中的对应形状以达到对图像分析和识别的目的。

关键点

    图像形态学操作主要是对二值图像进行操作的,来连接相邻的元素或分离成独立的元素。其次是灰度图像,但处理彩色图像几乎没有意义!

图像形态学操作主要有:

    膨胀、腐蚀、开运算、闭运算、梯度运算、礼帽运算、黑帽运算,击中与击不中变换 等等。其中膨胀和腐蚀是基本操作,后面的操作都是在膨胀和腐蚀的基础上延申而来的。

图像形态学操作有哪些应用领域

    由于对图像进行形态学操作后,可以实现比如消除噪声、提取边界、填充区域、提取连通分量、凸壳、细化、粗化等; 还可以分割出独立的图像元素,或者图像中相邻的元素;求取图像中明显的极大值区域和极小值区域;求取图像梯度等等, 所以在视觉检测、图像理解、文字识别、医学图像处理、图像压缩编码等领域有非常重要的应用。

    在进行各种形态学操作之前,先介绍一个至关重要的函数: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:InputArray src

    输入图像,图像数据类型必须为CV_8U, CV_16U, CV_16S, CV_32F or CV_64F中的一种。

参数2:OutputArray dst

    输出图像,数据类型与大小和输入图像一样。

参数3: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 :击中-击不中变换

参数4:InputArray kernel

    结构元矩阵

参数5:Point anchor = Point(-1,-1)

    结构元中心点, 默认值Point(-1,-1), 表示正中心

参数6:int iterations = 1

    腐蚀膨胀处理的次数,默认值为1;

如果是开运算闭运算,次数表示先腐蚀或者膨胀几次,再膨胀腐蚀几次,而不是开运算闭运算几次:

如开运算且次数为2:erode -> erode -> dilate -> dilate

参数7:int borderType = BORDER_CONSTANT

    图像边框插值类型,默认类型为固定值填充

BORDER_CONSTANT = 0:固定值 i 填充:iiiiii | abcdefgh | iiiiiii

BORDER_REPLICATE = 1:两端复制:aaaaaa | abcdefgh | hhhhhhh

BORDER_REFLECT = 2:镜像复制:fedcba | abcdefgh | hgfedcb

BORDER_WRAP = 3:去除一端的值然后复制: cdefgh | abcdefgh | abcdefg

BORDER_REFLECT_101 = 4:去除一端的值然后镜像复制: gfedcb|abcdefgh|gfedcba

BORDER_TRANSPARENT = 5:推导赋值 uvwxyz | abcdefgh | ijklmno

BORDER_REFLECT101 = BORDER_REFLECT_101: same as BORDER_REFLECT_101

BORDER_DEFAULT = BORDER_REFLECT_101: same as BORDER_REFLECT_101

BORDER_ISOLATED = 16:< do not look outside of ROI

参数8:const Scalar& borderValue = morphologyDefaultBorderValue()

    文档中说明:param borderValue Border value in case of a constant border. The default value has a special meaning.

    morphologyEx函数配合上自己定义的结构元矩阵kernel,就可以完成各种形态学操作。

以下是原始图、Sobel算子得到的梯度图以及大津法OTSU阈值分割之后的图片:
85cd3d8072b24342a30b0deef8f99895.png3408f0ed92c448f8ae262f16103bd515.png3b8b57bab9184a3eab157955e09cc943.png

其中大津法作用之后的二值图作为形态学操作的输入。

一、图像腐蚀

    顾名思义,是将物体的边缘加以腐蚀。具体的操作是拿一个宽m高n的矩形作为kernel,对图像中的每一个像素进行扫描,扫描后的图像的每个像素点和原图的位置对应,同时和扫描时kernel的中心点对应。用kernel遍历原图的所有像素,每遍历一次就将对应位置的像素点更改为kernel中的最小值。这样原图所有像素遍历一轮后,原图中突出的像素点就会被置为最小值,人类视觉看起来就是图像被腐蚀了。

Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	//进行形态学操作
morphologyEx(image, image, MORPH_ERODE, element);
imshow("【腐蚀效果图】", image);

1b985b5bf69941f1b8352d1a4f6df563.png

二、图像膨胀

    膨胀和腐蚀是一对儿相反的操作,膨胀能对图像的边界进行扩展,就是将图像的轮廓加以膨胀。
操作方法与腐蚀操作一样,也是拿一个kernel,对图像的每个像素做遍历处理。不同之处在于生成的像素值不是所有像素中最小的值,而是最大的值。这样操作的结果会将图像外围的突出点连接并向外延伸。

Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));  
	//进行形态学操作
morphologyEx(image, image, MORPH_DILATE, element);   //结果保存到自身
imshow("【膨胀效果图】", image);

26c262c1d2db4008ab695240d980ebf6.png

可见 指纹内部暗点消失,边界部分有细微的扩张。

三、图像开运算、闭运算、梯度运算、顶帽运算、底帽运算

    膨胀和腐蚀是图像形态学处理的基础,将膨胀和腐蚀通过不同方式结合起来就可以得到图像开运算、闭运算、梯度运算、顶帽运算、底帽运算等运算。

①开运算

     开运算(opening operation),其实就是先腐蚀后膨胀过得过程,可以用来消除小物体,在纤细点出分离物体,平滑较大物体的边界同时并不明显改变其面积。

Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	//进行形态学操作
morphologyEx(image, image, MORPH_OPEN, element);
imshow("【开运算效果图】", image);


25965ddcc6d04cc5ab1d70ee3eb5f489.png

 ②闭运算

    先膨胀后腐蚀的过程称为闭运算(closing operation), 闭运算能够排除小黑洞(黑色区域)。

Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	//进行形态学操作
morphologyEx(image, image, MORPH_CLOSE, element);
imshow("【闭运算效果图】", image);

  d9283062a98b4e4da77d886992f40ec7.png  

 ③形态学梯度

    形态学梯度(morphological gradient)为膨胀图与腐蚀图之差,对二值图像进行这一操作可以将团块(blob)的边缘突出来。

Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	//进行形态学操作
morphologyEx(image, image, MORPH_GRADIENT, element);
imshow("【形态学梯度效果图】", image);


5b50af41292746539d20401a12eb2f95.png

 ④顶帽运算

    顶帽运算(top hat) 又常常被译为“礼帽”运算,为原图像与“开运算”的结果图之差。因为开运算带来的结果是放大了裂缝或者局部低亮度的区域,因此,从原图中减去开运算后的图,得到的效果图突出了比原型轮廓周围的区域更明亮的区域。且这一操作和选择的核的大小有关。顶帽运算往往用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的时候,可以用顶帽运算进行背景提取。

Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	//进行形态学操作
morphologyEx(image, image, MORPH_TOPHAT, element);
imshow("【顶帽运算效果图】",image);

add56a703ede402bb8f0c8a1994fc05f.png

 ⑤底帽运算
    黑帽(Black Hat)运算为”闭运算“的结果图与原图像之差,黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关。所以,黑帽运算用来分离比邻近点暗一些的斑块。

Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	//进行形态学操作
morphologyEx(image, image, MORPH_BLACKHAT, element);
imshow("【黑帽运算效果图】", image);

f697d894d79c4ac288f82a9dee6a6506.png

 四、代码汇总

1.头文件,把各种操作封装到一个类中。

#include <opencv2/opencv.hpp>

using namespace cv;

class Shape_process{
public:
	void Dilation(Mat image);
	void Opening(Mat image);
	void Closing(Mat image);
	void Gradient(Mat image);
	void TopHat(Mat image);
	void BlackHat(Mat image);
	void ErodeEX(Mat image);
	Mat Sobel(Mat img);
	Mat OTSU(Mat img, int arr[]);
};

2.cpp文件,对类中方法进行定义。

#include<Test6.h>
#include<iostream>

using namespace std;

void Shape_process::Dilation(Mat image){
	namedWindow("【膨胀原始图】");
	namedWindow("【膨胀效果图】"); 
	imshow("【膨胀原始图】", image);
	Mat module = Mat::zeros(Size(image.cols, image.rows), image.type());
	//定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));  
	//进行形态学操作
	morphologyEx(image, module, MORPH_DILATE, element);
	imshow("【膨胀效果图】", module);
	waitKey(0);
}

void Shape_process::Opening(Mat image){
	namedWindow("【开运算原始图】");
	namedWindow("【开运算效果图】");
	imshow("【开运算原始图】", image);
	Mat module = Mat::zeros(Size(image.cols, image.rows), image.type());
	//定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	//进行形态学操作
	morphologyEx(image, module, MORPH_OPEN, element);
	imshow("【开运算效果图】", module);
	waitKey(0);
}

void Shape_process::Closing(Mat image){
	namedWindow("【闭运算原始图】");
	namedWindow("【闭运算效果图】");
	imshow("【闭运算原始图】", image);
	Mat module = Mat::zeros(Size(image.cols, image.rows), image.type());
	//定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	//进行形态学操作
	morphologyEx(image, module, MORPH_CLOSE, element);
	imshow("【闭运算效果图】", module);
	waitKey(0);
}

void Shape_process::Gradient(Mat image){
	namedWindow("【形态学梯度原始图】");
	namedWindow("【形态学梯度效果图】"); 
	imshow("【形态学梯度原始图】", image);
	Mat module = Mat::zeros(Size(image.cols, image.rows), image.type());
	//定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	//进行形态学操作
	morphologyEx(image, module, MORPH_GRADIENT, element);
	imshow("【形态学梯度效果图】", module);
	waitKey(0);
}

void Shape_process::TopHat(Mat image){
	namedWindow("【顶帽运算原始图】");
	namedWindow("【顶帽运算效果图】");
	imshow("【顶帽运算原始图】", image);
	Mat module = Mat::zeros(Size(image.cols, image.rows), image.type());
	//定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	//进行形态学操作
	morphologyEx(image, module, MORPH_TOPHAT, element);
	imshow("【顶帽运算效果图】", module);

	waitKey(0);
}

void Shape_process::BlackHat(Mat image){
	namedWindow("【黑帽运算原始图】");
	namedWindow("【黑帽运算效果图】"); 
	imshow("【黑帽运算原始图】", image);
	Mat module = Mat::zeros(Size(image.cols, image.rows), image.type());
	//定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	//进行形态学操作
	morphologyEx(image, module, MORPH_BLACKHAT, element);
	imshow("【黑帽运算效果图】", module);
	waitKey(0);
}

void Shape_process::ErodeEX(Mat image){
	namedWindow("【腐蚀原始图】");
	namedWindow("【腐蚀效果图】"); 
	imshow("【腐蚀原始图】", image);
	Mat module = Mat::zeros(Size(image.cols, image.rows), image.type());
	//定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	//进行形态学操作
	morphologyEx(image, module, MORPH_ERODE, element);
	imshow("【腐蚀效果图】", module);
	waitKey(0);
}

Mat Shape_process::Sobel(Mat img) {                   // 基于Prewitt算子的阈值分割
	Mat Sobel_Ojld = Mat::zeros(Size(img.cols, img.rows), img.type());  //用于计算欧几里得距离的空白图像
	for (int row = 1; row < img.rows - 1; row++) {
		for (int col = 1; col < img.cols - 1; col++) {
			Sobel_Ojld.at<uchar>(row, col) = saturate_cast<uchar>(sqrt(pow(img.at<uchar>(row - 1, col + 1) - img.at<uchar>(row - 1, col - 1) + 2 * img.at<uchar>(row, col + 1) - 2 * img.at<uchar>(row, col - 1) + img.at<uchar>(row + 1, col + 1) - img.at<uchar>(row + 1, col - 1), 2) + pow(img.at<uchar>(row + 1, col - 1) - img.at<uchar>(row - 1, col - 1) + 2 * img.at<uchar>(row + 1, col) - 2 * img.at<uchar>(row - 1, col) + img.at<uchar>(row + 1, col + 1) - img.at<uchar>(row - 1, col + 1), 2)));
		}
	}
	imshow("Sobel图像(欧几里得距离)", Sobel_Ojld);
	int pixel_num[256] = { 0 };            //数组记得初始化为0,即未统计数量之前各个像素的个数都是0
	for (int row = 0; row < img.rows; row++) {
		for (int col = 0; col < img.cols; col++) {
			pixel_num[Sobel_Ojld.at<uchar>(row, col)] += 1;   //遍历到的像素值作为索引,次数+1
		}
	}

	imshow("欧几里得阈值分割", Sobel_Ojld);

	Mat m1 = OTSU(Sobel_Ojld, pixel_num);     // OTSU阈值分割
	return m1;
}

Mat Shape_process::OTSU(Mat img, int arr[]) {   // 需要输入待处理的图像 和 直方图像素个数数组
	int N = img.rows * img.cols;    // 统计输入图像的像素个数N
	double pro[256] = { 0 };            // 定义概率数组
	for (int i = 0; i < 256; i++) {
		pro[i] = arr[i] / N;            // 得到每个像素值的概率
	}
	double delta = 0, w0 = 0, w1 = 0, u0 = 0, u1 = 0, v = 0;           // 变量初始化为0
	int T = 0, thresh = 0;
	while (T <= 255) {
		for (int i = 0; i <= T; i++) {
			w0 += pro[i];                       // C0的概率
		}
		w1 = 1 - w0;                            // C1的概率
		for (int i = 0; i <= 255; i++) {
			if (i <= T) {
				u0 += pro[i] * i;                     // C0的平均值
			}
			else {
				u1 += pro[i] * i;                     // C1的平均值
			}
			v = w0 * w1 * pow(u1 - u0, 2);
			if (v > delta) {
				delta = v;
				thresh = T;
			}
			T += 1;
		}
	}
    //由最佳像素阈值进行二值分割
	Mat OTSU = Mat::zeros(Size(img.cols, img.rows), img.type());
	for (int row = 0; row < img.rows; row++) {
		for (int col = 0; col < img.cols; col++) {
			if (img.at<uchar>(row, col) > thresh) {
				OTSU.at<uchar>(row, col) = 255;
			}
		}
	}
	return OTSU;
}

3.cpp文件,进行各种形态学操作。

#include <opencv2/opencv.hpp>
#include <Test6.h>

using namespace cv;

int main() {
	Mat Gray = imread("C:\\Users\\LLLiePP\\Desktop\\zhiwen.png", IMREAD_GRAYSCALE);
    if (Gray.empty())return -1;       //判断图片是否引入出错

	Shape_process test;
	Mat otsu = test.Sobel(Gray);

	test.Dilation(otsu);
	test.Opening(otsu);
	test.Closing(otsu);
	test.Gradient(otsu);
	test.TopHat(otsu);
	test.BlackHat(otsu);
	test.ErodeEX(otsu);

	return 0;
};

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/104239.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言 期末合集 pta

6-1 求最大的偶数和最小的奇数的差 分数 10 全屏浏览题目 切换布局 作者 王跃萍 单位 东北石油大学 求10个数中的最大的偶数和最小的奇数的差。 函数接口定义&#xff1a; int fun(int a[],int n); 函数fun中a、n是用户传入的参数&#xff0c;函数fun的功能是求a数组中的…

【LVGL学习笔记】(五)使用SquareLine Studio设计UI

LVGL全程LittleVGL&#xff0c;是一个轻量化的&#xff0c;开源的&#xff0c;用于嵌入式GUI设计的图形库。并且配合LVGL模拟器&#xff0c;可以在电脑对界面进行编辑显示&#xff0c;测试通过后再移植进嵌入式设备中&#xff0c;实现高效的项目开发。 LVGL中文教程手册&#…

点云地图构建及定位

点云地图构建及定位1. 回环检测1.1 基于Scan Context1.2 基于直方图2. 后端优化2.1 后端优化基本原理2.2 李群、李代数基本知识2.3 李群、李代数基本知识2.3.1 SO(3)\mathrm{SO}(3)SO(3) 对应的 BCH\mathrm{BCH}BCH 公式2.3.2 SE(3)\mathrm{SE}(3)SE(3) 对应的 BCH\mathrm{BCH}…

链式存储之:链表的引出及其简介

上篇博客&#xff0c;笔者讲解了一下顺序表ArrayList&#xff0c;对于ArrayList有想法的各位老铁可以看一下&#xff1a;值得思索的&#xff1a;ArrayList和线性表&#xff0c;你确定错过这次机会_念君思宁的博客-CSDN博客值得思索的&#xff1a;ArrayList和线性表&#xff0c;…

Html5 canvas创意特效合集

Canvas就像一块画布&#xff0c;我们可以通过调用脚本在Canvas上绘制任意形状&#xff0c;甚至是制作动画。本文就是收集了很多非常富有创意的一些canvas动画特效例子&#xff0c;这些例子都非常适合大家学习。 1.3D篝火动画特效 这款篝火特效是基于 three.js 和 canvas 制作的…

博实结将在创业板上会:计划募资25亿元,周小强为实际控制人

近日&#xff0c;深圳市博实结科技股份有限公司&#xff08;下称“博实结”&#xff09;在深圳证券交易所递交招股书&#xff08;上会稿&#xff09;&#xff0c;准备在创业板上市。据贝多财经了解&#xff0c;博实结将于2022年12月23日接受创业板上市委审议&#xff0c;一同上…

Vue3----props和emit的使用

作用&#xff1a;父组件通过 props 向下传递数据给子组件&#xff1b; 用途&#xff1a;当有一种类型的组件需要被使用多次&#xff0c;每一次的调用都只是特定的地方不同&#xff0c;就好像一张个人简介表&#xff0c;每次填的人的信息都不同&#xff0c;但是结构都是一样的。…

Nacos学习笔记 (2)Nacos基础核心特性

内容&#xff1a; Nacos架构及其核心特性&#xff0c;包括服务注册、服务发现、发布与获取配置特性&#xff0c;以及Nacos Spring关键特性。 本文内容&#xff0c;参考 Nacos 官网与 《Nacos架构&原理》一书。 1. Nacos 架构 详情推荐参考&#xff1a; &#xff08;1&a…

服务器取证——服务器基础知识

目录 一、服务器基本介绍 &#xff08;一&#xff09;概念 &#xff08;二&#xff09;构成 &#xff08;三&#xff09; 种类 &#xff08;四&#xff09;与pc区别 二、 磁盘阵列RAID &#xff08;一&#xff09;概念 &#xff08;二&#xff09;产生原因 &#xff0…

【Django】第二课 银行账户管理系统开发

概念 本文在上一篇文章基础之前进行构建和完善 账户信息的分页显示 用户通过点击首页的“查询账户”&#xff0c;进入账户信息查询页面 则点击该按钮触发点击事件&#xff0c;向django服务器发出请求 接着我们在urls.py中需要定义与该地址进行匹配的地址&#xff0c;并匹配后…

Java on VS Code 12月更新年度亮点回顾|实时内存视图、注入处理器支持与用户体验改进

作者&#xff1a;Nick Zhu - Senior Program Manager, Developer Division at Microsoft 排版&#xff1a;Alan Wang 大家好&#xff0c;一年的时间过得很快&#xff0c;我们已经来到了2022年的年底。回顾 2022 年&#xff0c;我们的产品也经历了很多的迭代&#xff0c;在此之中…

甲氧基聚乙二醇二苯并环辛烯mPEG-DBCO简介DBCO-mPEG科研实验用试剂

中文名&#xff1a;甲氧基聚乙二醇二苯并环辛烯 英文名&#xff1a;mPEG-DBCO&#xff1b;DBCO-mPEG 分子量: 1K.2K.5K.10k.20k.30k 溶解度: DMSO, DMF 储存条件: -20C 状态&#xff1a;淡黄色到白色固体&#xff0c;或者半固体&#xff0c;取决于分子量。 溶解性&#x…

网心科技马婷:探寻边缘计算的“诗和远方”

​​LiveVideoStackCon 2022上海站活动结束&#xff0c;每一次大会的举办对音视频领域都是新的洗礼&#xff0c;同时也带来了新的收获和挑战。随着音视频技术在各种行业、场景中的逐渐成熟&#xff0c;更多的业务形态、产品变换 、跨界案例等越来越多的部分值得我们探寻和研究。…

「网络工程师必会技能」-路由器介绍和路由器基本配置

「网络工程师必会技能」-路由器介绍和路由器基本配置&#xff0c;这是每个网络必须会的技能&#xff0c;不是你有证书就一个网络工程师了哦&#xff01; 以Cisco路由器为例说明&#xff1a; &#xff08;1&#xff09;访问路由器。访问路由器与访问交换机一样&#xff0c;可以…

医院陪护小程序,专业的事情交给专业的人

陪诊服务这几年一直受到人们的好评&#xff0c;有了医院陪护小程序之后一些无法居家照顾老人的子女可以通过小程序为老人预约服务&#xff0c;陪诊平台的出现还让陪诊员有了正规的接单平台&#xff0c;不仅方便了人们下单找陪诊员还可以对陪诊人员坐正规的管理。那么在开发医院…

33.前端笔记-CSS3-2D转换

目录1、转换2、二维坐标系2.1 2D转换之移动translate2.2 2D旋转之rotate练习1练习2练习32.3 2D转换之缩放scale练习1练习22D转换综合写法转换综合练习1、转换 转换transform是CSS3中具有颠覆性的特征之一&#xff0c;可以实现元素的位移、旋转、缩放等效果 2、二维坐标系 2.…

Fabric.js 修改画布交互方式到底有什么用?

本文简介 点赞 关注 收藏 学会了 fabric.js 为我们提供了很多厉害的方法。今天要搞明白的一个东西是 canvas.interactive 。 官方文档对 canvas.interactive 的解释是&#xff1a; Indicates that canvas is interactive. This property should not be changed. canvas.in…

FPU与VFP最全面解释

本文希望能将FPU以及ARM中的FPU介绍清楚。 1. FPU&#xff08;Floating-Point Unit&#xff09; 浮点运算单元是处理器内部用于执行浮点数计算的逻辑部件&#xff0c;或者说硬件电路。不是所有的处理器都有该功能。浮点运算满足IEEE 754的标准&#xff0c;所谓IEEE 754标准&a…

关于Linux的动静态库

文章目录什么是动静态库生成静态库生成发布生成动态库发布使用库使用静态库查看系统头文件路径查看系统库文件路径使用库文件和头文件指定路径搜索头文件卸载库使用动态库动态库的运行搜索路径什么是动静态库 静态库&#xff08;.a&#xff09;&#xff1a;程序在编译链接的时…

再携手,齐并进!菊风助力宁波银行坐席PUSH外呼项目

随着“金融数字化”逐步成为金融行业的新浪潮&#xff0c;运用更加灵活的触达手段提升营销效果&#xff0c;促成业务闭环愈发成为银行业等金融机构角逐数字化转型成功的关键。 在此背景下&#xff0c;金融机构对于实时音视频技术的应用也从普遍的「呼入」需求逐步扩展到创新的…