【2】图像视频的加载和显示
文章目录
- 【2】图像视频的加载和显示
- 一、代码在哪写
- 二、创建和显示窗口
- (一)导入OpenCV的包`cv2`
- (二)创建窗口
- (三)更改窗口大小 & 显示窗口
- (四)等待用户输入
- 补充:ord()函数来返回ASCII值
- (五)销毁窗口
- (※)完整代码
- 二、加载显示图片
- (一)cv2.imread()返回值
- (二)用matplotlib显示图片
- (三)用OpenCV显示图片
- (1)封装函数
- (2)封装外部.py文件
- (四)保存图片
- 三、视频采集和录制
- (一)视频采集
- (二)视频录制
- 四、控制鼠标
- 五、TrackBar控件
【2】图像视频的加载和显示
一、代码在哪写
注:上一节中已经创建好了虚拟环境。
打开Anaconda Prompt,切换到我们已经创建好的opencv
虚拟环境下。
我们使用jupyter notebook来写代码。(输入jupyter notebook
)
之后,就弹出一个控制台页面。
弹出的这些东西就不太对了。
为什么会弹出这一堆东西,原因在于:你在哪个目录下执行的jupyter notebook
命令,它就会以哪个目录作为根目录。
可见,此时这一堆东西都是我的C:\Users\11202
目录下的文件,这些文件肯定都是不能动的,我们也不应该以这里作为我们写代码的目录。
也就是说,上述是一个错误的演示。
正确的应该怎么做呢?如下。
如果是继续刚才的命令往下写,那么需要按两下ctrl+C
把刚才打开的jupyter notebook先退出。
如果是关掉,又新打开的Anaconda Prompt,则不要忘了使用activate opencv先跳转到需要的虚拟环境下。
然后我们使用cd
命令,打开到我们想要作为根目录的路径(我的是D:\ANACONDA\dirs\test2409
),然后再使用命令jupyter notebook
。
注意:从C盘跳转到D盘时,不要写成cd D:
,而是直接输入D:
。之后,跳转到D盘后,再使用cd
去打开对应文件夹。
这时,再跳转到的控制页面就是我们想要的了。之后我们可以在里面新建一个notebook,就可以写代码了。
二、创建和显示窗口
namedWindow()
创建命名窗口imshow()
显示窗口destroyAllwindows()
摧毁窗口resizeWindow()
改变窗口大小waitKey()
等待用户输入
我们依次试一下其效果。
(一)导入OpenCV的包cv2
注意:OpenCV名字虽然叫OpenCV,但是在导包的时候,导入的包叫作cv2
。(这是个历史遗留问题,很早的时候它就叫cv,之后进行了重构,于是又叫cv2了,并沿用至今)
运行没有报错,说明正确导入此包。说明我们之前的环境配置、包的安装等操作都是顺利的。
(二)创建窗口
注意:光标放在函数上,按shift+tab
可以显示对该函数用法的说明(按一下是简洁版说明,按两下是详细版说明)。这个功能也是使用jupyter notebook所带来的一个好处。
注意:如果发现按
shift+tab
无效,则首先检查一下是否执行过import cv2
代码,因为有时候你刚打开这个文件直接就去shift+tab
,发现显示不出说明。实际上是因为没有导入cv2的包,导致它不认识这个函数,自然也就不会给出说明。
这个函数的用法是,括号的内的第一个参数,是窗口名字
(注意,应当是一个字符串)。后面的参数是窗口标记
(可以从函数用法说明中阅读到具体介绍)。
可见,不同的窗口标记,可以使窗口以不同的风格进行显示;以及如果不注明窗口标记,则会有一个默认值。
注意:如果想要设置flag
这一参数,仅仅输入对应标记名是不够的,还要在前面加上cv2.
,如cv2.WINDOW_AUTOSIZE
。(注意标记名不要写错)
运行后,的确会出现一个窗口,说明代码没问题,但是是未响应状态,这是因为我们写的不是一个规范的写法。
注意:我们把
import cv2
与创建窗口代码
写在两个不同的代码框中,此时,务必要保证先运行了import cv2
之后,再去运行创建窗口代码
,否则会报错(报错原因是找不到cv2这个包)。或者你就把所有代码都写在同一个框里。
(三)更改窗口大小 & 显示窗口
cv2.resizeWindow()
的第一个参数为要修改大小的窗口名
,后两个参数为窗口大小尺寸
。
cv2.imshow()
的第一个参数为要显示的窗口名
,第二个参数为要显示的图片
。此处我们没有什么要显示的图片,因此第二个参数设置为0。
此外,需要注意的是,对于我们创建窗口时设置的窗口标记
,若设置的是cv2.WINDOW_AUTOSIZE
(根据内容自动调节窗口尺寸),那么你修改窗口大小是没有效果的。
注意,注释单行代码的快捷键:
ctrl+/
。
(四)等待用户输入
cv2.waitKey()
的作用是,等待接收用户按键,并返回该按键对应的ASCII码值。
其中参数设置为0,表示一直等待、接收任意按键。如果设置其他的整数,表示等待按键的时间(单位是毫秒)。比如设置为cv2.waitKey(5000)
,就表示它会等你5秒,在5秒之内你按键才有用,过了5秒就不等你了。
注意,此时观察左侧,是In [*]
,是星号说明这段代码正在运行中,还没有运行结束。
实际上,cv2.waitKey(0)
的作用就是等待用户按一个键。当然,焦点要在窗口上时才可以。
我按了一个键盘上的q键,它就会捕捉到并输出一个113
。113
就是q的ASCII码值。(注意是小写q,不是大写Q)
补充:ord()函数来返回ASCII值
(五)销毁窗口
我们可以配合cv2.waitKey(0)
,先接收到用户按键的ASCII码值,然后就能根据用户按的是什么键,判断是否要销毁窗口了。(常用的比如q键、ESC键)。
按下q键后,窗口直接被销毁(关闭),而不会再有窗口未响应的问题。
但是由于程序只接收一次按键,如果你按的不是q键,它还是会有窗口未响应的问题。
注意,如果对于
key == 'q'
为什么有问题有疑问,则需要补一补python基础。
(※)完整代码
# ------------------------- 创建和显示窗口 -------------------------# opencv名字叫opencv,但是导包的时候叫做cv2
import cv2# 创建窗口
# 注意,cv2.WINDOW_AUTOSIZE则后续修改窗口大小无效
# cv2.namedWindow('myWindow01', cv2.WINDOW_AUTOSIZE)
cv2.namedWindow('myWindow01', cv2.WINDOW_NORMAL)# 更改窗口大小
cv2.resizeWindow('myWindow01', 800, 600)# 显示指定名字的窗口
cv2.imshow('myWindow01', 0)# 等待按键
# 若用户按键为q键,则销毁窗口
key = cv2.waitKey(0) # 先用变量key接收
# 注意,这样写更易读,而不要写key == 113,即使你知道q是113
# 注意,不要写成key == 'q'
if key == ord('q'):print('准备销毁窗口')cv2.destroyAllWindows()# ------------------------- 创建和显示窗口 -------------------------
二、加载显示图片
imread(path, flag)
使用imread可以读取图片,默认读取的是彩色图片。
path是图片的路径(绝对路径、相对路径都可以)。
flag是以什么方式读取这个图片(比如读出来是黑白的)。
(一)cv2.imread()返回值
# 导入opencv包
import cv2# 读取图片
cat = cv2.imread('./1.png')# numpy的ndarray(多维数组)
cat
输出如下:
array([[[ 1, 12, 90],[ 2, 12, 91],[ 1, 13, 91],...,[ 3, 10, 61],[ 4, 9, 61],[ 4, 9, 65]],[[ 3, 13, 91],[ 3, 13, 92],[ 2, 14, 92],...,[ 2, 11, 60],[ 2, 10, 60],[ 2, 9, 63]],[[ 2, 12, 91],[ 2, 13, 91],[ 2, 14, 92],...,[ 3, 10, 60],[ 3, 10, 60],[ 3, 10, 62]],...,[[ 4, 31, 111],[ 4, 32, 112],[ 4, 31, 113],...,[119, 190, 208],[119, 190, 208],[119, 190, 208]],[[ 5, 31, 111],[ 5, 31, 111],[ 5, 31, 112],...,[119, 190, 208],[119, 190, 208],[119, 190, 208]],[[ 6, 32, 111],[ 6, 31, 111],[ 6, 31, 111],...,[118, 189, 207],[119, 190, 208],[119, 190, 208]]], dtype=uint8)
(二)用matplotlib显示图片
import matplotlib.pyplot as pltplt.imshow(cat)
我的原图是:
输出结果如下:
发现这个猫的样子没变,但是颜色不太对。这是因为OpenCV读取的图片颜色通道是按照BGR(蓝绿红)排列的,一般的图片通道都是按照RGB来排列的。
为了正常显示图片,我们要使用OpenCV的图像显示方法。换句话说,用OpenCV读进来的图片一般不要用别的方式进行展示,比如matplotlib。
(三)用OpenCV显示图片
cv2.imshow('cat', cat)# 按键以销毁窗口,避免每次都有窗口未响应的问题
key = cv2.waitKey(0)
if key == ord('q'):print('准备销毁窗口')cv2.destroyAllWindows()
这样就会弹出一个窗口,并正常显示该图片,我们可以按下q键以正常关闭窗口。
(1)封装函数
此外,我们可以把显示图片的方法封装成一个函数,方便我们显示图片:
# 把展示图片的代码封装成函数
def cv_show(name, img):cv2.imshow(name, img)key = cv2.waitKey(0)if key == ord('q'):cv2.destroyAllWindows()
之后想显示图片的时候,直接调用函数即可:
# 导入opencv包
import cv2# 读取图片
cat = cv2.imread('./1.png')cv_show('cat', cat)
(2)封装外部.py文件
我们可以在当前目录下创建一个.py
文件,把封装的函数代码放进去。
注意,如果这样放代码,那么在调用的时候会报错。因为,在utils.py
这个文件中,我们调用了cv2
,但是并没有导入cv2
,就会报错。
需要在函数中调用cv2之前,先import cv2
。
这样就可以正常运行了。
注意:如果还是有问题,可以使用%run utils.py
执行一下外部文件(这是在jupyter中执行外部文件的方法),看看外部文件本身是否运行不了。如果在执行外部文件时报错IndentationError: unindent does not match any outer indentation level
,则是代码缩进问题,一般是tab和空格混用导致的缩进问题,这个问题仅凭肉眼是不容易看出来的(新手容易踩的坑)。(如果使用的是notepad++,可以通过View--Show Symbol--Show All Characters
来检查这一问题)
(四)保存图片
imwrite(path, img)
:使用imwrite保存图片。
import cv2cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cv2.resizeWindow('img', 320, 240)img = cv2.imread('./1.png')# 利用while循环优化退出逻辑
while True:cv2.imshow('img', img)key = cv2.waitKey(0)if(key & 0xFF == ord('q')):breakelif(key & 0xFF == ord('s')):cv2.imwrite('./123.png', img)else:print(key)cv2.destroyAllWindows()
三、视频采集和录制
(一)视频采集
- 视频是由图片组成的,视频的每一帧就是一幅图片,一般是30帧,表示一秒显示30张图片。
cv2.VideoCapture
可以捕获摄像头,用数字来表示不同的设备,比如0、1。- 如果是视频文件,可以直接指定路径即可。
# 打开视频文件
vc = cv2.VideoCapture('./1.mp4')# 打开摄像头
vc = cv2.VideoCapture(0)
打开摄像头
示例:
# 打开摄像头
import cv2cv2.namedWindow('video', cv2.WINDOW_NORMAL)
cv2.resizeWindow('video', 640, 480)# 如果打开失败(比如没有摄像头),不会报错
# cap = cv2.VideoCapture(1) # 我只有摄像头0,没有摄像头1
cap = cv2.VideoCapture(0)# 循环读取摄像头的每一帧
# while True:
while cap.isOpened():# 读一帧数据,返回标记和这一帧数据,标记为True表示读到了数据,False表示没读到数据ret, frame = cap.read()# 可以根据ret做个判断if not ret:# 没读到数据,直接退出break# 显示数据cv2.imshow('video', frame)key = cv2.waitKey(1)# 注意,此处就不要再写0了,因为写0表示无限等待,也就是显示一帧数据然后一直等待用户按键# 写个1,表示等1毫秒,若等不到按键就继续处理了if key == ord('q'):break# 别忘了释放资源
cap.release()
cv2.destroyAllWindows()
打开视频文件
示例:
# 打开摄像头
import cv2cv2.namedWindow('video', cv2.WINDOW_NORMAL)
cv2.resizeWindow('video', 640, 480)# 打开视频,传入视频路径即可
cap = cv2.VideoCapture('./1.mp4')# 循环读取摄像头的每一帧
# while True:
while cap.isOpened():# 读一帧数据,返回标记和这一帧数据,标记为True表示读到了数据,False表示没读到数据ret, frame = cap.read()# 可以根据ret做个判断if not ret:# 没读到数据,直接退出break# 显示数据cv2.imshow('video', frame)key = cv2.waitKey(1)# 注意,此处就不要再写0了,因为写0表示无限等待,也就是显示一帧数据然后一直等待用户按键# 写个1,表示等1毫秒,若等不到按键就继续处理了# key = cv2.waitKey(1000 // 30) # 让视频以30帧播放if key == ord('q'):break# 别忘了释放资源
cap.release()
cv2.destroyAllWindows()
注意,上述代码,和刚才“打开摄像头”的代码只有一行不同,即第8行的cap = cv2.VideoCapture('./1.mp4')
,其他地方都相同。
运行此代码时,发现其播放的视频好像加速了一样,这是因为,第24行代码的key = cv2.waitKey(1)
造成的效果是每等待1毫秒显示一帧数据,所以播放的比较快。
假如我们想让视频是30帧,那么每张图片要间隔多少毫秒?
答:理论上来说,是1000 / 30
ms,但此处传递的参数必须是整数,所以我们代码写成1000 // 30
。(Python语法,//
表示向下取整)
另外,我们此处处理的是视频中每一帧的图片,所以没有声音。
(二)视频录制
VideoWriter
:参数1为输出文件,参数2为多媒体文件格式(VideoWriter_fourcc
),参数3为帧率,参数4为分辨率;write
编码并写入缓存;release
缓存内容写入磁盘,并释放资源。
import cv2cap = cv2.VideoCapture(0)# *mp4v 就是解包操作,等同于 'm','p','4','v'
# fourcc = cv2.VideoWriter_fourcc(*'mp4v')# avi格式的视频
fourcc = cv2.VideoWriter_fourcc(*'XVID')# (640, 480)表示摄像头拍视频的分辨率,这个大小搞错了也不行
# vw = cv2.VideoWriter('output.mp4', fourcc, 20, (640, 480))# 如果前面写的是avi,这里要改成avi格式
vw = cv2.VideoWriter('output.avi', fourcc, 20, (640, 480))while cap.isOpened():ret, frame = cap.read()if not ret:print('can not receive frame, Exiting...')breakvw.write(frame)cv2.imshow('frame', frame)if cv2.waitKey(1) == ord('q'):breakcap.release()vw.release()cv2.destroyAllWindows()
四、控制鼠标
OpenCV允许我们对窗口上的鼠标动作做出响应。
setMouseCallback(winname, callback, userdata)
:winname是窗口名字,callback是回调函数,userdata是给回调函数的参数。callback(event, x, y, flags, userdata)
:回调函数必须包含这5个参数。event是事件(鼠标移动、左键、右键),xy是点鼠标的坐标点,flags主要用于组合键,userdata就是上面的setMouseCallback的userdata。
鼠标事件:
EVENT_MOUSEMOVE 0 鼠标移动
EVENT_LBUTTONDOWN 1 按下鼠标左键
EVENT_RBUTTONDOWN 2 按下鼠标右键
EVENT_MBUTTONDOWN 3 按下鼠标中键
EVENT_LBUTTONUP 4 左键释放
EVENT_RBUTTONUP 5 右键释放
EVENT_MBUTTONUP 6 中键释放
EVENT_LBUTTONDBLCLK 7 左键双击
EVENT_RBUTTONDBLCLK 8 右键双击
EVENT_MBUTTONDBLCLK 9 中键双击
EVENT_MOUSEWHEEL 10 鼠标滚轮上下滚动
EVENT_MOUSEHWHEEL 11 鼠标左右滚动flags:
EVENT_FLAG_LBUTTON 1 按下左键
EVENT_FLAG_RBUTTON 2 按下右键
EVENT_FLAG_MBUTTON 4 按下中键
EVENT_FLAG_CTRLKEY 8 按下ctrl键
EVENT_FLAG_SHIFTKEY 16 按下shift键
EVENT_FLAG_ALTKEY 32 按下alt键
示例:
import cv2
import numpy as np# 函数名可以随便取,但是参数必须是5个(参数名也可以随便取)
# event表示鼠标事件
# x, y是发生鼠标事件的坐标
# flags是鼠标的组合操作
def mouse_callback(event, x, y, flags, userdata):print(event, x, y, flags, userdata)# 按下鼠标右键退出if event == 2:cv2.destroyAllWindows()# 创建窗口
cv2.namedWindow('mouse', cv2.WINDOW_NORMAL)
cv2.resizeWindow('mouse', 640, 360)# 设置鼠标的回调函数
cv2.setMouseCallback('mouse', mouse_callback, '123')# 生成全黑的图片
img = np.zeros((360, 640, 3), np.uint8)while True:cv2.imshow('mouse', img)key = cv2.waitKey(1)if key == ord('q'):breakcv2.destroyAllWindows()
五、TrackBar控件
createTrackbar(trackbarname, winname, value, count, onChange)
:创建TrackBar控件,value为trackbar的默认值,count为bar的最大值,最小为0。getTrackbarPos(trackbarname, winname)
:获取TrackBar当前值。
示例:
import cv2
import numpy as np# 创建窗口
cv2.namedWindow('trackbar', cv2.WINDOW_NORMAL)
cv2.resizeWindow('trackbar', 640, 480)# 定义回调函数
def callback(value):print(value)# 创建trackbar
cv2.createTrackbar('R', 'trackbar', 0, 255, callback)
cv2.createTrackbar('G', 'trackbar', 0, 255, callback)
cv2.createTrackbar('B', 'trackbar', 0, 255, callback)# 创建一个背景图片
img = np.zeros((480, 640, 3), np.uint8)while True:# 获取当前trackbar的值r = cv2.getTrackbarPos('R', 'trackbar')g = cv2.getTrackbarPos('G', 'trackbar')b = cv2.getTrackbarPos('B', 'trackbar')# 改变背景图颜色img[:] = [b, g, r]cv2.imshow('trackbar', img)key = cv2.waitKey(1)if key & 0xFF == ord('q'):breakcv2.destroyAllWindows()
相关文章:

【2】图像视频的加载和显示
文章目录 【2】图像视频的加载和显示一、代码在哪写二、创建和显示窗口(一)导入OpenCV的包cv2(二)创建窗口(三)更改窗口大小 & 显示窗口(四)等待用户输入补充:ord()函…...

1. BOOT.BIN 2. 固化 3. 启动 4. SDK 5. 文件
在进行FPGA的开发与固化过程中,生成BOOT.BIN文件是一个重要的步骤。BOOT.BIN文件通常包含了系统启动所需的不同文件,以下是如何创建和使用该文件的详细说明。 ### 生成BOOT.BIN文件的步骤 1. **方法一:通过项目构建** - 右键单击项目…...

vue按钮接收键盘回车事件
了解了!如果您想让 Submit 按钮在按下回车键时被触发,可以在 Vue 组件中监听全局的键盘事件。以下是实现这一功能的示例: 示例代码 <template><div><inputtype"text"v-model"inputValue"placeholder&qu…...

腾讯云点播及声音上传
文章目录 1、开通腾讯云点播2、获取腾讯云API密钥3、完成声音上传3.1、引入依赖3.2、参考:接入点地域3.3、参考:任务流设置3.4、首先修改配置:3.4.1、 3.5、TrackInfoApiController --》 uploadTrack()3.6、VodServiceImpl --》 uploadTrack(…...

如何查看服务器是否有raid阵列卡以及raid类型
要查看服务器是否配置了RAID阵列卡以及RAID的类型,可以使用多种方法。以下是一些常用的命令和步骤: 1. 使用 lspci 命令 这个命令可以列出所有的PCI设备,包括RAID控制器。 lspci | grep -i raid 如果输出中有RAID相关的设备信息,那…...

工博会动态 | 来8.1馆 看桥田如何玩转全场
北京时间2024年9月24日,中国国际工业博览会开幕,桥田智能(8.1馆A001)推出心意三重奏,有没有小伙伴们发现呢?现在,让我们一起city walk下! 桥田显眼包横空出道 有小伙伴已经发现&…...

新版torch_geometric不存在uniform、maybe_num_nodes函数问题(Prune4ED论文报错解决)
这是在复现论文“Towards accurate subgraph similarity computation via neural graph pruning”时遇到的报错。 ImportError: cannot import name uniform from torch_geometric.nn.pool.topk_pool 一、报错原因 论文作者使用的是2.1.0版本的torch_geometric。而我安装了2.…...

实现简易 vuedraggable 的拖拽排序功能
一、案例效果 拖拽计数4实现手动排序 二、案例代码 <draggable:list"searchResult.indicator":group"{ name: indicators }"item-key"field"handle".drag-handle-icon"><divclass"field-item"v-for"(item…...

第L2周:机器学习|线性回归模型 LinearRegression:2. 多元线性回归模型
本文为365天深度学习训练营 中的学习记录博客原作者:K同学啊 任务: ●1. 学习本文的多元线形回归模型。 ●2. 参考文本预测花瓣宽度的方法,选用其他三个变量来预测花瓣长度。 一、多元线性回归 简单线性回归:影响 Y 的因素唯一&…...

JavaScript的条件语句
if条件语句 if结构先判断一个表达式的布尔值,然后根据布尔值的真伪,执行不同的语句。所谓布尔值,指的是JavaScript 的两个特殊值,true表示真,false表示伪。 if语句语法规范 if(布尔值){语句;}var m3if(m3){console.l…...

vue3 vite模式配置测试,开发、生产环境以及代理配置
1、首先在根目录下创建三个文本文件:.env.development,.env.production,.env.test .env.development中的内容为: // 开发环境 .env.development NODE_ENV development VITE_APP_MODE development VITE_OUTPUTDIR dist_dev /…...

【rabbitmq-server】安装使用介绍
在 1050a 系统下安装 rabbitmq-server 服务以及基本配置;【注】:改方案用于A版统信服务器操作系统 文章目录 功能概述功能介绍一、安装软件包二、启动服务三、验证四、基本配置功能概述 RabbitMQ 是AMQP的实现,高性能的企业消息的新标准。RabbitMQ服务器是一个强大和可扩展…...

Kafka系列之:安装部署CMAK,CMAK管理大型Kafka集群参数调优
Kafka系列之:安装部署CMAK,CMAK管理大型Kafka集群参数调优 一、CMAK二、要求三、配置四、启动服务五、使用 Security 启动服务六、消费者/生产者滞后七、从 Kafka Manager 迁移到 CMAK八、CMAK管理大型Kafka集群参数调优九、后台运行CMAK十、输出日志一、CMAK CMAK(之前称为…...

c语言200例 64
大家好,欢迎来到无限大的频道。 今天带领大家来学习c语言。 题目要求: 设计一个进行候选人的选票程序。假设有三位候选人,在屏幕上输入要选择的候选人姓名, 有10次投票机会,最后输出每个人的得票结果。好的ÿ…...

[leetcode]216_组合总和III_给定数字范围且输出无重复
找出所有相加之和为 n 的 k 个数的组合,且满足下列条件: 只使用数字1到9 每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。示例 1: 输入: k 3, n 7 输出: [[1,2,4]] 解释: 1…...

Doris 2.x 安装及使用
Doris 2.x 安装及使用 简介 Apache Doris 是一款基于 MPP 架构的高性能、实时的分析型数据库,以高效、简单、统一的特点被人们所熟知,仅需亚秒级响应时间即可返回海量数据下的查询结果,不仅可以支持高并发的点查询场景,也能支持…...

MySQL字符集设置
MySQL字符集设置 一、查看当前配置的字符集 \s;示例 MariaDB [(none)]> \s -------------- mysql Ver 15.1 Distrib 5.5.68-MariaDB, for Linux (x86_64) using readline 5.1Connection id: 11 Current database: Current user: rootlocalhost SSL: …...

深度学习模型量化
模型量化是深度学习领域中的一项重要技术,它通过降低模型参数的精度,将浮点数转换为整数或定点数,从而实现模型的压缩和优化。以下是进行模型量化的详细步骤和注意事项: 一、模型量化的基本步骤 选择量化方法 后训练量化…...

红黑树和B+树
红黑树和B树是两种常用的自平衡数据结构,适用于不同的应用场景和需求。下面是对这两种树的详细比较和描述: 红黑树 基本结构: 红黑树是一种自平衡的二叉搜索树(Binary Search Tree),其中每个节点都有一个颜…...

debian 12配置固定ip
配置文件 cat /etc/network/interfaces |grep -v # source /etc/network/interfaces.d/*auto lo iface lo inet loopbackallow-hotplug ens18 iface ens18 inet staticaddress 192.168.0.105/24network 192.168.0.0broadcast 192.168.0.255gateway 192.168.0.1dns-nameserver…...

OceanBase技术解析: 执行器中的自适应技术
在《OceanBase 数据库源码解析》这本书中,对于执行器的探讨还不够深入,它更多地聚焦于执行器的并行处理机制。因此,通过本文与大家分享OceanBase执行器中几种典型的自适应技术,作为对书中执行器部分的一个补充。 提升数据库分析性…...

Spring Cloud Gateway接入WebSocket:实现实时通信
在现代的微服务架构中,实时通信变得越来越重要。Spring Cloud Gateway作为Spring Cloud生态中的API网关,提供了动态路由、监控、弹性、安全等功能。本文将介绍如何通过Spring Cloud Gateway接入WebSocket,实现服务之间的实时通信。 为什么需…...

linux信号| 学习信号三步走 | 学习信号需要打通哪些知识脉络?
前言: 本节内容主要讲解linux下信号的预备知识以及信号的概念, 信号部分我们将会分为几个阶段进行讲解:信号的概念, 信号的产生, 信号的保存。本节主要讲解信号 ps:本节内容适合学习了进程相关概念的友友们进行观看哦 目录 什么是…...

Java调用第三方接口、http请求详解,一文学会
Java 调用第三方接口的封装方法详解 在开发企业级应用时,调用第三方接口是非常常见的场景。我们可能需要与外部服务集成,如支付接口、短信接口、天气服务接口等。为了提高代码的可维护性、复用性和易扩展性,封装第三方接口调用的方法非常重要…...

windows10使用bat脚本安装前后端环境之redis注册服务
首先需要搞清楚redis在本地是怎么安装配置、然后在根据如下步骤编写bat脚本: 思路 1.下载zip格式redis 2.查看windows server服务是否已安装redis 3.启动查看服务是否正常 bat脚本 echo off echo windows10 x64 server redis init REM 请求管理员权限并隐藏窗口 …...

fastapp-微信开发GPT项目第一课
0. 开发说明 在学习开发本项目之前,必须保证有以下知识储备和环境工具。 技术栈说明python>3.9、pydantic>2.7.1python基础,http协议fastapi>0.111.0web协程异步框架,有web开发基础,异步编程,类型标注[pyth…...

在双十一必买的好物有哪些?2024年双十一好物清单分享
一年一度的双十一购物狂欢节再次悄然临近,它不仅是一场购物的盛宴,更是我们提前规划生活、享受优惠的绝佳时机,在这个全民狂欢的日子里,各大品牌纷纷亮出杀手锏,推出年度最给力的优惠和新品,让人目不暇接&a…...

避免glibc版本而报错,CentOS等Linux安装node.js完美方法
概述 对于Node.js v18.x或更高,Node.js官方默认是在Ubuntu 20.04, Debian 10, RHEL 8,CentOS 8等高版操作系统上编译得到的,高版本操作系统的glibc版本≥2.28。所以,下载Node.js后,也需要glibc版本≥2.28才能使用。 而CentOS 7.x等…...

elasticsearch实战应用
Elasticsearch是一个基于Lucene的分布式、实时全文搜索引擎,广泛应用于日志收集和可视化、数据分析以及大规模数据检索等领域。其强大的搜索和分析能力,使得Elasticsearch成为许多企业和开发者在处理大规模数据时的首选工具。以下将从Elasticsearch的实战…...

STM32精确控制步进电机
目的:学习使用STM32电机驱动器步进电机,进行电机运动精确控制。 测试环境: MCU主控芯片STM32F103RCT6 ;A4988步进电机驱动器模块; 微型2相4线步…...