【C++的OpenCV】第五课-OpenCV图像常用操作(二):OpenCV的基本绘图、平滑滤波(模糊)处理

news2024/11/17 4:26:32

让我们继续

  • 一、OpenCV基本绘图
    • 1.1 OpenCV关于绘图的操作
      • 1.1.1 cv::Point()
      • 1.1.2 cv::Scalar()
      • 1.1.3 cv::line()画线
      • 1.1.4 cv::rectangle()画矩形
      • 1.1.5 cv::circle()画圆
  • 二、图像的平滑滤波处理
    • 2.1 概念
    • 2.2 OpenCV关于图像模糊的操作
      • 2.2.1 常用滤波器的分类
      • 2.2.2 各种滤波方法具体的代码实现
    • 2.3 参考源码

前文链接:
【C++的OpenCV】第四课-OpenCV图像常用操作(一):Mat对象深化学习、灰度、ROI

一、OpenCV基本绘图

1.1 OpenCV关于绘图的操作

1.1.1 cv::Point()

// Point类型的源码来源:
typedef Point2i cv::Point  //规定cv::Point2i类型为cv::Point

typedef Point_<int> cv::Point2i  // 规定将cv::Point_<int> 类型为 cv::Point12i,最常用,以此为例
	// 同理还存在:typedef Point_<float> cv::Point2f 和 
				//typedef Point_<double> cv::Point2d

// 实际上参考的类型为cv::Point_<int>,故在源码中我们要找到类模板 class  cv::Point_< _Tp >
typedef _Tp 	value_type // 又将类模板中的类型_Tp 定为 value_type.
// 这里,我们讨论value_type为int的情况,即cv::Point类型,如果不理解,多看上边几行转化逻辑!

        关于cv::Point()的常用的构造函数:
在这里插入图片描述
        源码位置:Point()类型的源码解释

  • Point_() :默认的构造函数
template<typename _Tp>
cv::Point_< _Tp >::Point_(	)	
  • Point_() : 基于点xy轴坐标的构造函数
template<typename _Tp>
cv::Point_< _Tp >::Point_(	_Tp _x, _Tp _y )	

//参数解释:
1、_Tp _x : 
	template<typename _Tp>
	_Tp cv::Point_< _Tp >::x
点point的x轴坐标

2、_Tp _y :
	template<typename _Tp>
	_Tp cv::Point_< _Tp >::y
点Point的y轴坐标

//以坐标创建一个点对象的示例:
		//使用起来其实很简单,关键是看懂源码对大家大有帮助,
		//工具的使用和理解中,我认为理解工具更重要,所以为大家进行了源码解析。
//示例1:
Point pt;
pt.x = 3;
pt.y = 4;

//示例2:
Point pt = Point(3,4);
  • Point_() :拷贝构造函数
cv::Point_< _Tp >::Point_	(	const Point_< _Tp > & 	pt	)	

// 参数解释:
1、pt :为另外一个点对象,且对象保证了传递对象过程中的安全性(const修饰),
		将另一个点的数据拷贝到新的点上。
  • Point_() :根据Size对象来构造点
template<typename _Tp>
cv::Point_< _Tp >::Point_	(	const Size_< _Tp > & 	sz	)	

// 参数解释:
1、 sz:一个Size对象,同样保证传递安装性。
Template class for specifying the size of an image or rectangle.

// 关于Size:该类包括两个名为width和height的成员。
		// 该结构可以转换为旧的OpenCV结构CvSize和CvSize2D32f。
// 可以使用与Point_相同的一组算术和比较操作。

1.1.2 cv::Scalar()

// Scalar 类的由来和功能
// 由来:
typedef Scalar_<double> cv::Scalar  // Scalar类实际上就是Scalar_<double>类
// 其类模板为:
template<typename _Tp>
class cv::Scalar_< _Tp >  // 当_Tp为double类型时,为Scalar()类
//从Vec派生的4元素向量的模板类。
//从Vec<_Tp,4>导出,Scalar_和Scalar可以用作典型的4元素向量。
//此外,它们还可以转换为CvScalar或从CvScala转换。Scalar类型在OpenCV中广泛用于传递像素值。

        关于cv::Scalar()的常用的构造函数:
在这里插入图片描述
        源码位置:Scalar()类的构造函数

  • Scalar_()的构造函数
1、默认构造函数:
template<typename _Tp>
cv::Scalar_< _Tp >::Scalar_	()	

2、四向量值构造函数:
template<typename _Tp>
cv::Scalar_< _Tp >::Scalar_	(	_Tp 	v0,
								_Tp 	v1,
								_Tp 	v2 = 0,
								_Tp 	v3 = 0 
							)		

//这个构造函数和拷贝构造函数使用频率较高
//广泛使用它来表示BGR颜色值(3个参数)。如果不使用最后一个参数,则无需定义最后一个参数。
//我们被要求一个颜色参数:
Scalar( a, b, c )
//我们将定义一个BGR颜色,如:Blue = a,Green = b和Red = c

3、拷贝构造函数:
template<typename _Tp>
cv::Scalar_< _Tp >::Scalar_	(	const Scalar_< _Tp > & 	s	)	

4、单值构造函数:
template<typename _Tp>
cv::Scalar_< _Tp >::Scalar_	(	_Tp 	v0	)	

5、Vec容器类构造函数:
template<typename _Tp>
template<typename _Tp2 , int cn>
cv::Scalar_< _Tp >::Scalar_	(	const Vec< _Tp2, cn > & 	v	)	

// _Tp2为通道数据类型,cn为通道数。

// 要论Scalar还有什么用途,只要理解其本质“传递像素值”即可灵活使用。

1.1.3 cv::line()画线

  • 函数原型:
void cv::line	(	InputOutputArray 	img,
					Point 	pt1,
					Point 	pt2,
					const Scalar & 	color,
					int 	thickness = 1,
					int 	lineType = LINE_8,
					int 	shift = 0 
				)		
  • 参数解释:
1、img :画在哪里,即背景板,是一个Mat对象(或是InputOutputArray类型同类型即可)
2、pt1、pt2:划线的两个点(划线原理是在两个点之间划线
3、color :Scalar类型的颜色描述,例如:Scalar( 255, 0, 0 ) 
4、thickness:线条的粗细,这个自己根据画出来的情况调节即可
5、lineType:线的类型,下边展示类型的宏作为选择参考。
6、shift:点坐标中的小数位数。0位没有小数位即整数。
  • 函数功能:
绘制连接两点的线段。
函数线绘制图像中pt1和pt2点之间的线段。
线条由图像边界剪裁。对于具有整数坐标的非抗锯齿线,
使用8连通或4连通Bresenham算法。粗线以圆角结尾绘制。
使用高斯滤波绘制抗锯齿线。
  • 关于线的类型的宏:
    在这里插入图片描述
  • 实例:
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#define w 400

using namespace cv;

void DrawLine( Mat img, Point , Point );// 划线函数前置声明

int main( int argc, char* argv[] ){
  char windowName[] = "Drawing Window";//显示图像的窗口的名称
  Mat img = Mat::zeros( w, w, CV_8UC3 );//长宽各400像素的8位3通道无符号的空白图像矩阵
         
  MyLine( img, Point( 0, w/2 ), Point( w/4, w/2 ) ); // 画一条位于图像y方向中间的水平线,且长度为100像素

  imshow( windowName, img ); // 将图片显示在窗口中
  waitKey( 0 );
  return(0);
}

void DrawLine( Mat img, Point s, Point e )
{
  int lineThickness = 3;
  int lineType = LINE_8;
  line( img,s,e,Scalar( 0, 0, 0 ),lineThickness,lineType );//调用划线函数,线的色彩为白色
}

1.1.4 cv::rectangle()画矩形

  • 函数原型:

void cv::rectangle	(	InputOutputArray 	img,
						Point 	pt1,
						Point 	pt2,
						const Scalar & 	color,
						int 	thickness = 1,
						int 	lineType = LINE_8,
						int 	shift = 0 
)	
  • 参数解释:
1、pt1、pt2:矩形对角线的点
2、其他参数同划线函数。
  • 函数功能:
向右上方绘制简单、粗或填充的矩形。
函数cv::rectangle()绘制矩形轮廓或填充矩形,其两个对角为pt1和pt2。
  • 实例:
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

using namespace cv;

int main( void ){
  char rook_window[] = "Drawing 2: Rook";

  Mat rook_image = Mat::zeros( w, w, CV_8UC3 );
  
  rectangle( rook_image,
         Point( 0, 7*400/8 ),
         Point( 400, 400),
         Scalar( 0, 255, 255 ),
         FILLED,
         LINE_8 );
         
  imshow( rook_window, rook_image );
  moveWindow( rook_window, 400, 200 );
  waitKey( 0 );
  return(0);
  //这里就不一行一行解释代码了,上边画线看懂了,这个自然很轻松,主要是复习而已,大家多看看哈!
}

1.1.5 cv::circle()画圆

  • 函数原型:

void cv::circle	(	InputOutputArray 	img,
					Point 	center,
					int 	radius,
					const Scalar & 	color,
					int 	thickness = 1,
					int 	lineType = LINE_8,
					int 	shift = 0 
				)	
  • 参数解释:
1、center : 圆中心点坐标
2、radius:圆的半径
3、剩下的参数不必多言,如果大家认真看了划线的讲解,大家就都懂了
  • 函数功能:
画个圆圈圈!
  • 实例
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#define w 400
using namespace cv;

void DrawFilledCircle( Mat img, Point center ) // 小编实在懒得写前置声明了,这个图省事,当然标准格式还是参照划线的代码吧
{
  circle( img,
      center,
      w/32,
      Scalar( 0, 0, 255 ),
      FILLED,
      LINE_8 );
}

int main( void ){
  char window[] = "Drawing Window";
  Mat image = Mat::zeros( w, w, CV_8UC3 );

  MyFilledCircle( atom_image, Point( w/2, w/2) );// 画布中心(200,200)的位置画圆

  imshow( window, image );
  waitKey( 0 );
  return(0);
}

二、图像的平滑滤波处理

2.1 概念

    平滑滤波,也称之为模糊,是一种简单的图像处理的操作。
    至于模糊的目的,一般情况下最多的情况用于降噪,其次用于边界检测的相关处理也是比较广泛的,当然其他用途还是得看具体的业务。

2.2 OpenCV关于图像模糊的操作

    对于模糊处理,通常会使用到滤波器来处理图像。

2.2.1 常用滤波器的分类

  • 归一化框(方框/块)滤波:
            这个过滤器是最简单的!每个输出像素是其内核相邻区域的均值(均为相等权重)
            其内核如下:
    在这里插入图片描述
  • 高斯滤波器
            可能是最有用的过滤器(虽然不是最快的)。高斯滤波是通过将输入数组中的每个点与高斯核进行卷积来完成的,然后将它们相加以产生输出数组。位于中间的像素将具有最大的权重。其邻居的权重随着它们与中心像素之间的空间距离的增加而减小。
            其内核如下:
    在这里插入图片描述
  • 中值滤波器
            中值滤波器遍历信号的每个元素(在这种情况下为图像),并用其相邻像素的中位数(位于估计像素周围的正方形邻域)替换每个像素。
  • 双边滤波器
            与高斯滤波器类似的方式,双边滤波器也考虑相邻像素,其权重分配给它们。这些权重具有两个分量,其中第一个是高斯滤波器使用的相同加权。第二个组件考虑了相邻像素与被评估的像素之间的强度差异。

2.2.2 各种滤波方法具体的代码实现

  • 归一化滤波
    • OpenCV提供函数cv :: blur()来使用此过滤器进行平滑处理。
void cv::blur(
				InputArray src,
				OutputArray dst,
				Size ksize,
				Point anchor = Point(-1,-1),
				int borderType = BORDER_DEFAULT 
			)		

/*
参数解释:
1、src:源图像(Mat对象),它可以有任意数量的通道,这些通道是独立处理的,
	但深度应该是CV_8U、CV_16U、CV_36S、CV_32F或CV_64F。
2、dst:目标图像(Mat对象),输出的图像和源图像同类型和同尺寸。
3、ksize:滤波器使用的内核的大小(Size(x,y)宽度为w像素和高度h像素)。
4、anchor:锚点,默认值(Point(-1,-1))在所选择大小的内核的中心。
5、borderType:用于图像扩张外部像素的边框模式,
	请参见边框类型(BORDERTYPE)。不支持BORDER_WRAP。
*/
    • 关于BORDERTYPE的参考值:BORDERTYPE类型参考
      在这里插入图片描述
  • 高斯滤波
void cv::GaussianBlur	(	
							InputArray 	src,
							OutputArray 	dst,
							Size 	ksize,
							double 	sigmaX,
							double 	sigmaY = 0,
							int 	borderType = BORDER_DEFAULT 
						)		

/*
参数解释:
1、sigmaX:X方向的高斯核标准偏差。
2、sigmaY: Y方向的高斯核标准偏差(默认为0)。
其余参数同之前。
*/

关于这个方法中提及的XY方向上距离高斯核的偏差,大家可以简单理解为,模糊的情况。
  • 中值滤波

void cv::medianBlur	(	
						InputArray 	src,
						OutputArray 	dst,
						int 	ksize 
)		

// 参数解释:
// ksize:内核的线性尺寸;它必须是奇数且大于1,例如:3、5、7。。。
  • 双边滤波

void cv::bilateralFilter	(	
								InputArray 	src,
								OutputArray 	dst,
								int 	d,
								double 	sigmaColor,
								double 	sigmaSpace,
								int 	borderType = BORDER_DEFAULT 
							)

/*
参数解释:
1、d:过滤过程中使用的每个像素邻域的直径。
	如果它是非正的,则从sigmaSpace计算。
2、sigmaColor:颜色空间中的西格玛值。
	该参数的值越大,意味着像素邻域(请参见sigmaSpace)中的颜色越远,
	将混合在一起,从而产生更大的半等色区域。
3、sigmaSpace:在坐标空间中过滤西格玛值。
	该参数的值越大,意味着只要颜色足够接近,
	更远的像素就会相互影响(请参见sigmaColor)。
	当d>0时,它指定邻域大小,而不考虑sigmaSpace。
	否则,d与sigmaSpace成比例。
*/	

        双边滤波器可以很好地减少不需要的噪声,同时保持边缘相当清晰。然而,与大多数过滤器相比,它非常慢。
        sigma值:为了简单起见,可以将2西格玛值设置为相同。如果它们很小(<10),滤镜将不会有太大的效果,而如果它们很大(>150),它们将有非常强的效果,使图像看起来“卡通”。
        过滤器大小:大型过滤器(d>5)非常慢,因此建议对实时应用程序使用d=5,对需要重噪声过滤的脱机应用程序使用d=9。

2.3 参考源码

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace std;
using namespace cv;
int DELAY_CAPTION = 1500;
int DELAY_BLUR = 100;
int MAX_KERNEL_LENGTH = 31;
Mat src; Mat dst;
char window_name[] = "Smoothing Demo";
int display_caption( const char* caption );
int display_dst( int delay );
int main( void )
{
  namedWindow( window_name, WINDOW_AUTOSIZE );
  src = imread( "../data/lena.jpg", IMREAD_COLOR );
  if( display_caption( "Original Image" ) != 0 ) { return 0; }
  dst = src.clone();
  if( display_dst( DELAY_CAPTION ) != 0 ) { return 0; }
  if( display_caption( "Homogeneous Blur" ) != 0 ) { return 0; }
  for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
      { blur( src, dst, Size( i, i ), Point(-1,-1) );
        if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
  if( display_caption( "Gaussian Blur" ) != 0 ) { return 0; }
  for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
      { GaussianBlur( src, dst, Size( i, i ), 0, 0 );
        if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
  if( display_caption( "Median Blur" ) != 0 ) { return 0; }
  for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
      { medianBlur ( src, dst, i );
        if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
  if( display_caption( "Bilateral Blur" ) != 0 ) { return 0; }
  for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
      { bilateralFilter ( src, dst, i, i*2, i/2 );
        if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
  display_caption( "End: Press a key!" );
  waitKey(0);
  return 0;
}
int display_caption( const char* caption )
{
  dst = Mat::zeros( src.size(), src.type() );
  putText( dst, caption,
           Point( src.cols/4, src.rows/2),
           FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );
  imshow( window_name, dst );
  int c = waitKey( DELAY_CAPTION );
  if( c >= 0 ) { return -1; }
  return 0;
}
int display_dst( int delay )
{
  imshow( window_name, dst );
  int c = waitKey ( delay );
  if( c >= 0 ) { return -1; }
  return 0;
}

大家可以在自己电脑的相关位置找到这个源码:…/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp
        孜孜不倦,持续更新。期待关注!

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

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

相关文章

【4】linux命令每日分享——cd切换路径

大家好&#xff0c;这里是sdust-vrlab&#xff0c;Linux是一种免费使用和自由传播的 类UNIX操作系统&#xff0c;Linux的基本思想有两点&#xff1a;一切都是文件&#xff1b;每个文件都有确定的用途&#xff1b;linux涉及到IT行业的方方面面&#xff0c;在我们日常的学习中&am…

云计算学习课程——越来越重要的云安全

2023&#xff0c;越来越多的企业和组织正在或即将把核心系统和数据迁移上云端&#xff0c;其中以公有云和服务居多&#xff0c;那么就意味着在数据迁移的过程中会出现安全问题的几率更大。企业也越来越注重云安全体系&#xff0c;对我们云计算运维工程师来说&#xff0c;也是一…

Linux 日志讲解

目录 日志系统的分类 常见日志文件 日志等级 journalctl查看指定日志信息 日志系统的分类 系统日志 记录系统的运行情况和内核信息 用户日志 记录用户的访问信息 程序日志 记录程序运行的各种时间&#xff08;每个服务程序都有自己独立的日志文件&#x…

UE4 手把手教你做插件(4)做一个可以拖入场景的小方块插件

0&#xff0c;前言 学习一下如何编写一个有actor的插件&#xff0c;能够将它拖入场景里面。 1&#xff0c;创建插件 &#xff08;1&#xff09;创建一个空白插件 添加之后vs里面就会多出一个目录&#xff1a; &#xff08;2&#xff09;给插件添加一个actor 创建完actor之后&am…

渗透测试之交换式网络嗅探实验

渗透测试之交换式网络嗅探实验实验目的一、实验原理1.1 网络嗅探器Sniffer的工作原理1.2 网络嗅探器的分类1.3 网络嗅探器Sniffer的作用二、实验环境2.1 操作机器2.2 实验工具Sniffer2.3 安装工具Sniffer三、实验步骤1. 熟悉Sniffer工具的启动2. 进行监听3. 熟悉Sniffer工具的介…

Python数据结构与算法篇(四)-- 链表的实现

实现线性表的另一种常用方式就是基于链接结构&#xff0c;用链接关系显式表示元素之间的顺序关联。基于链接技术实现的线性表称为链接表或者链表。 采用链接方式实现线性表的基本想法如下: 把表中的元素分别存储在一批独立的存储块&#xff08;称为表的结点&#xff09;里。保…

刷题记录:牛客NC51112Stars in Your Window 扫描线

传送门:牛客 题目描述: Here comes the problem: Assume the sky is a flat plane. All the stars lie on it with a location (x, y). for each star, there is a grade ranging from 1 to 100, representing its brightness, where 100 is the brightest and 1 is the we…

数据库大量数据导出导入的操作

基于上一篇文章&#xff0c;我想到如果在数据库之间拥有大量数据的表数据的导入导出&#xff0c;该如何快速完成表的导入导出工作呢&#xff1f; 思路一:使用db软件工具导出数据&#xff0c;然后向新数据库导入数据。我用的是dbserver22.3.4&#xff0c;不出意外的是&#xff0…

【读书笔记】《深入浅出数据分析》第二章 检验你的理论

文章目录一&#xff0c;相关分析方法1&#xff0c;相关系数二&#xff0c;相关性不等于因果关系三&#xff0c;证明因果关系&#xff0c;“控制变量法”?本章主要说明了两个问题&#xff1a; 1&#xff0c;相关性不等于因果关系 2&#xff0c;如何判断两种数据之间是相关性&am…

深圳/东莞/惠州师资比较强的CPDA数据分析认证

深圳/东莞/惠州师资比较强的CPDA数据分析认证培训机构 CPDA数据分析师认证是中国大数据领域有一定权威度的中高端人才认证&#xff0c;它不仅是中国较早大数据专业技术人才认证、更是中国大数据时代先行者&#xff0c;具有广泛的社会认知度和权威性。 无论是地方政府引进人才、…

Android 高性能列表:RecyclerView + DiffUtil

文章目录背景介绍一般刷新 notifyDataSetChanged()局部刷新实现调用代码准备工作创建 MyDiffUtilCallback 类继承 DiffUtil.Callback 抽象类MyAdpter 类代码实现步骤总结通过 log 证实 diffutil 的局部刷新diffutil 优化后台线程参考主线程参考diff 更新优化后写法相关参考背景…

Spring的一些知识点

什么是Spring&#xff1f; Spring是一种轻量级的开发框架&#xff0c;旨在提高开发人员的开发效率以及系统的可维护性。 Spring的核心模块 Spring Core是基础模块&#xff0c;可以说Spring的其他功能都要依赖于该类库&#xff0c;主要提供IOC的依赖注入功能&#xff1b; Spri…

动手学深度学习v2—01数据操作+数据预处理

此次用到的虚拟环境&#xff1a;pytorchmwy项目名称&#xff1a;limuAI所需框架和工具&#xff1a;pytorch&#xff0c;pandas一、创建CSV文件所需工具&#xff1a;pandas在与项目同等目录下创建一个文件夹名为data&#xff0c;其中文件名称为house_tiny.csv。代码如下&#xf…

Java基础:拼图小游戏

涉及到的知识: 1.图形用户接口GUI(Graphical User Interface)用图形化的方式显示操作界面 两个体系: AWT包和Swing包 2.界面会用到JFrame类 3.界面中的菜单会用到JMenuBar, JMenu, JMenuItem 4.添加图片 在设置完JLabel的location之后还需要获得展示内容的窗体, 通过setLay…

吃鸡用什么蓝牙耳机效果好?手游吃鸡公认最好的几款蓝牙耳机

蓝牙耳机的作用很多&#xff0c;几乎每个人都需要一副很棒的耳机在通勤或锻炼途中使用&#xff0c;并且玩游戏也少不了它&#xff0c;手游近几年十分的流行&#xff0c;下面整理了几款性能不错的蓝牙耳机。 第一款&#xff1a;南卡小音舱蓝牙耳机 蓝牙版本&#xff1a;5.3 发…

【Linux】如何将ntfs硬盘挂载到home目录下并具有读写权限

步骤1. 查看当前挂载的硬盘及其挂载点2. 查看需要挂载到home下的磁盘类型信息3. 在home下新建一个空的文件夹作为该磁盘的新挂载点4. 以ntfs类型的硬盘为例&#xff0c;使用mount命令进行挂载5. 问题1&#xff1a;进程占用了磁盘6. 问题2&#xff1a;磁盘权限为只读的7. 永久挂…

[AI助力] 2022.2.23 考研英语学习 2010 英语二翻译

[AI助力] 2022.2.23 考研英语学习 2010 英语二翻译 文章目录[AI助力] 2022.2.23 考研英语学习 2010 英语二翻译2010年英语二翻译真题自己写的积累&#x1f9d0;看看AI的翻译&#xff0c;学习学习&#xff08;把自己当成阅卷老师来康康hhh&#x1f920;DeepL谷歌翻译ReadPaper里…

JavaUDP通信程序

2 UDP通信程序 2.1 UDP通信原理 UDP协议是一种不可靠的网络协议&#xff0c;它在通信的两端各建立一个Socket对象, 但是这两个Socket只是发送&#xff0c;接收数据的对象因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念 Java提供了DatagramSocket类作为基…

低代码选型,论协同开发的重要性

Git是一款用于分布式版本控制的免费开源软件: 它可以跟踪到所有文件集中任意的变更&#xff0c;通常用于在软件开发期间&#xff0c;协调配合程序员之间的代码程序开发工作。 Git 最初诞生的原因源于Linux 内核的开发&#xff0c;2005年Linus Torvalds 编写出了Git。其他内核开…

AI作画—中国画之山水画

山水画&#xff0c;简称“山水”&#xff0c;中国画的一种&#xff0c;描写山川自然景色为主体的绘画。山水画在我国绘画史中占有重要的地位。 山水画形成于魏晋南北朝时期&#xff0c;但尚未从人物画中完全分离。隋唐时始终独立&#xff0c;五代、北宋时趋于成熟&#xff0c;…