计算机视觉 | OpenCV 实现手势虚拟控制亮度和音量
Hi,大家好,我是半亩花海。在当今科技飞速发展的时代,我们身边充斥着各种智能设备,然而,如何更便捷地与这些设备进行交互却是一个不断被探索的课题。本文将主要介绍一个基于 OpenCV 的手势识别项目,通过手势来控制电脑屏幕亮度和音量大小,为用户提供了一种全新的交互方式。
目录
一、代码拆解
1. 导入必要库
2. 初始化手部关键点
3. 数据格式转换
4. 画手势关键点
5. 手势状态缓冲处理
6. 画直线
7. 屏幕亮度和音量控制
8. 初始化摄像头和手部关键点识别器
9. Pygame 界面初始化和事件监听
二、实战演示
1. 亮度——light
2. 音量——voice
三、完整代码
一、代码拆解
1. 导入必要库
在开始介绍项目的实现细节之前,我们首先需要导入项目所需的必要库。这些库包括:
- OpenCV:用于处理图像和视频数据。
- Mediapipe:提供了对手部关键点的识别和跟踪功能。
- Pygame:用于创建图形界面和显示摄像头捕获的图像。
- WMI:用于调节电脑屏幕亮度。
- pycaw:用于控制电脑的音量。
# 导入必要库
import math
import sys
import numpy as np
import cv2
import pygame
import wmi
import mediapipe as mp
from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
import warnings # 忽略警告
warnings.filterwarnings("ignore")
2. 初始化手部关键点
首先创建一个 HandKeyPoint 类,用于初始化手部关键点检测器,并提供对图像进行处理的方法。
# 手部关键点类
class HandKeyPoint:def __init__(self,static_image_mode=False,max_num_hands=2,model_complexity=1,min_detection_confidence=0.5,min_tracking_confidence=0.5):# 手部识别apiself.mp_hands = mp.solutions.hands# 获取手部识别类self.hands = self.mp_hands.Hands(static_image_mode=static_image_mode,max_num_hands=max_num_hands,model_complexity=model_complexity,min_detection_confidence=min_detection_confidence,min_tracking_confidence=min_tracking_confidence)def process(self, image):# 将BGR转换为RGBimg = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)# 识别图像中的手势,并返回结果results = self.hands.process(img)# numpy格式的数据np_arr = landmarks_to_numpy(results)return results, np_arr
3. 数据格式转换
将手部关键点的检测结果(将 landmarks 格式的数据)转换为 numpy 数组,以便后续的处理和分析。
# 将landmarks格式的数据转换为numpy格式的数据
def landmarks_to_numpy(results):"""将landmarks格式的数据转换为numpy格式的数据numpy shape:(2, 21, 3):param results::return:"""shape = (2, 21, 3)landmarks = results.multi_hand_landmarksif landmarks is None:# 没有检测到手return np.zeros(shape)elif len(landmarks) == 1:# 检测出一只手,先判断是左手还是右手label = results.multi_handedness[0].classification[0].labelhand = landmarks[0]# print(label)if label == "Left":return np.array([np.array([[hand.landmark[i].x, hand.landmark[i].y, hand.landmark[i].z] for i in range(21)]),np.zeros((21, 3))])else:return np.array([np.zeros((21, 3)),np.array([[hand.landmark[i].x, hand.landmark[i].y, hand.landmark[i].z] for i in range(21)])])elif len(landmarks) == 2:# print(results.multi_handedness)lh_idx = 0rh_idx = 0for idx, hand_type in enumerate(results.multi_handedness):label = hand_type.classification[0].labelif label == 'Left':lh_idx = idxif label == 'Right':rh_idx = idxlh = np.array([[landmarks[lh_idx].landmark[i].x, landmarks[lh_idx].landmark[i].y, landmarks[lh_idx].landmark[i].z] for iin range(21)])rh = np.array([[landmarks[rh_idx].landmark[i].x, landmarks[rh_idx].landmark[i].y, landmarks[rh_idx].landmark[i].z] for iin range(21)])return np.array([lh, rh])else:return np.zeros((2, 21, 3))
4. 画手势关键点
# 画手势关键点
def draw_landmark(img, results):if results.multi_hand_landmarks:for hand_landmark in results.multi_hand_landmarks:mp.solutions.drawing_utils.draw_landmarks(img,hand_landmark,mp.solutions.hands.HAND_CONNECTIONS,mp.solutions.drawing_styles.get_default_hand_landmarks_style(),mp.solutions.drawing_styles.get_default_hand_connections_style())return img
5. 手势状态缓冲处理
为了平滑处理手势状态的变化,我们实现了一个 Buffer 类,用于缓存手势状态的变化,并提供了添加正例和负例的方法。
# 缓冲区类
class Buffer:def __init__(self, volume=20):self.__positive = 0self.state = Falseself.__negative = 0self.__volume = volumeself.__count = 0def add_positive(self):self.__count += 1if self.__positive >= self.__volume:# 如果正例个数大于容量,将状态定为Trueself.state = Trueself.__negative = 0self.__count = 0else:self.__positive += 1if self.__count > self.__volume:# 如果大于容量次操作后还没有确定状态self.__positive = 0self.__count = 0def add_negative(self):self.__count += 1if self.__negative >= self.__volume:# 如果负例个数大于容量,将状态定为Falseself.state = Falseself.__positive = 0else:self.__negative += 1if self.__count > self.__volume:# 如果大于容量次操作后还没有确定状态self.__positive = 0self.__count = 0# print(f"pos:{self.__positive} neg:{self.__negative} count:{self.__count}")def clear(self):self.__positive = 0self.state = Falseself.__negative = 0self.__count = 0
6. 画直线
# 画线函数
def draw_line(frame, p1, p2, color=(255, 127, 0), thickness=3):"""画一条直线:param p1::param p2::return:"""return cv2.line(frame, (int(p1[0] * CAM_W), int(p1[1] * CAM_H)), (int(p2[0] * CAM_W), int(p2[1] * CAM_H)), color,thickness)
7. 屏幕亮度和音量控制
# 控制屏幕亮度
def screen_change(percent): # percent/2即为亮度百分比SCREEN = wmi.WMI(namespace='root/WMI')a = SCREEN.WmiMonitorBrightnessMethods()[0]a.WmiSetBrightness(Brightness=percent, Timeout=500)# 初始化音量控制
def init_voice():devices = AudioUtilities.GetSpeakers()interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)volume = cast(interface, POINTER(IAudioEndpointVolume))volume.SetMute(0, None)volume_range = volume.GetVolumeRange()min_volume = volume_range[0]max_volume = volume_range[1]return (min_volume, max_volume), volume
8. 初始化摄像头和手部关键点识别器
在项目的初始化阶段,我们需要加载摄像头实例和手部关键点识别实例,以便后续对手势进行识别和处理。
# 加载摄像头实例
cap = cv2.VideoCapture(0)
CAM_W = 640
CAM_H = 480
CAM_SCALE = CAM_W / CAM_H# 加载手部关键点识别实例
hand = HandKeyPoint()
9. Pygame 界面初始化和事件监听
为了展示手势控制效果,并提供交互界面,我们使用了 Pygame 库。在初始化阶段,我们创建了一个窗口,并设置了标题。同时,我们实现了事件监听功能,以便在需要时退出程序。
具体来说,我们使用 Pygame 创建了一个窗口,并将摄像头捕获的图像显示在窗口中。同时,我们利用 Pygame 的事件监听功能,监听用户的键盘事件,例如按下"q"键时退出程序。这样,用户就可以通过手势控制屏幕亮度和音量大小,同时在 Pygame 窗口中观察手势识别效果。
# 初始化pygame
pygame.init()
# 设置窗口全屏
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("virtual_control_screen")
# 获取当前窗口大小
window_size = list(screen.get_size())# 主循环
while True:
······# 事件监听 若按q则退出程序for event in pygame.event.get():if event.type == pygame.KEYDOWN:if event.key == pygame.K_q:sys.exit(0)
二、实战演示
1. 亮度——light
如果 20 < angle < 90,那么“light ready”即手势控制亮度。

2. 音量——voice
如果 -20 > angle > -50,那么“voice ready”即手势控制音量。

3. 菜单——menu
上述两种情况除外,那么处于“menu”状态即进入菜单。

通过演示可以发现,食指与大拇指在屏幕中的距离越远,亮度越高(音量越大),反之越小,实现了通过手势对亮度和音量的控制。
三、完整代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
@Project : virtual
@File : virtual_control.py
@IDE : PyCharm
@Author : 半亩花海
@Date : 2024:02:06 18:01
"""
# 导入模块
import math
import sys
import numpy as np
import cv2
import pygame
import wmi
import mediapipe as mp
from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
import warnings # 忽略警告
warnings.filterwarnings("ignore")# 手部关键点类
class HandKeyPoint:def __init__(self,static_image_mode=False,max_num_hands=2,model_complexity=1,min_detection_confidence=0.5,min_tracking_confidence=0.5):# 手部识别apiself.mp_hands = mp.solutions.hands# 获取手部识别类self.hands = self.mp_hands.Hands(static_image_mode=static_image_mode,max_num_hands=max_num_hands,model_complexity=model_complexity,min_detection_confidence=min_detection_confidence,min_tracking_confidence=min_tracking_confidence)def process(self, image):# 将BGR转换为RGBimg = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)# 识别图像中的手势,并返回结果results = self.hands.process(img)# numpy格式的数据np_arr = landmarks_to_numpy(results)return results, np_arr# 将landmarks格式的数据转换为numpy格式的数据
def landmarks_to_numpy(results):"""将landmarks格式的数据转换为numpy格式的数据numpy shape:(2, 21, 3):param results::return:"""shape = (2, 21, 3)landmarks = results.multi_hand_landmarksif landmarks is None:# 没有检测到手return np.zeros(shape)elif len(landmarks) == 1:# 检测出一只手,先判断是左手还是右手label = results.multi_handedness[0].classification[0].labelhand = landmarks[0]# print(label)if label == "Left":return np.array([np.array([[hand.landmark[i].x, hand.landmark[i].y, hand.landmark[i].z] for i in range(21)]),np.zeros((21, 3))])else:return np.array([np.zeros((21, 3)),np.array([[hand.landmark[i].x, hand.landmark[i].y, hand.landmark[i].z] for i in range(21)])])elif len(landmarks) == 2:# print(results.multi_handedness)lh_idx = 0rh_idx = 0for idx, hand_type in enumerate(results.multi_handedness):label = hand_type.classification[0].labelif label == 'Left':lh_idx = idxif label == 'Right':rh_idx = idxlh = np.array([[landmarks[lh_idx].landmark[i].x, landmarks[lh_idx].landmark[i].y, landmarks[lh_idx].landmark[i].z] for iin range(21)])rh = np.array([[landmarks[rh_idx].landmark[i].x, landmarks[rh_idx].landmark[i].y, landmarks[rh_idx].landmark[i].z] for iin range(21)])return np.array([lh, rh])else:return np.zeros((2, 21, 3))# 画手势关键点
def draw_landmark(img, results):if results.multi_hand_landmarks:for hand_landmark in results.multi_hand_landmarks:mp.solutions.drawing_utils.draw_landmarks(img,hand_landmark,mp.solutions.hands.HAND_CONNECTIONS,mp.solutions.drawing_styles.get_default_hand_landmarks_style(),mp.solutions.drawing_styles.get_default_hand_connections_style())return img# 缓冲区类
class Buffer:def __init__(self, volume=20):self.__positive = 0self.state = Falseself.__negative = 0self.__volume = volumeself.__count = 0def add_positive(self):self.__count += 1if self.__positive >= self.__volume:# 如果正例个数大于容量,将状态定为Trueself.state = Trueself.__negative = 0self.__count = 0else:self.__positive += 1if self.__count > self.__volume:# 如果大于容量次操作后还没有确定状态self.__positive = 0self.__count = 0def add_negative(self):self.__count += 1if self.__negative >= self.__volume:# 如果负例个数大于容量,将状态定为Falseself.state = Falseself.__positive = 0else:self.__negative += 1if self.__count > self.__volume:# 如果大于容量次操作后还没有确定状态self.__positive = 0self.__count = 0# print(f"pos:{self.__positive} neg:{self.__negative} count:{self.__count}")def clear(self):self.__positive = 0self.state = Falseself.__negative = 0self.__count = 0# 画线函数
def draw_line(frame, p1, p2, color=(255, 127, 0), thickness=3):"""画一条直线:param p1::param p2::return:"""return cv2.line(frame, (int(p1[0] * CAM_W), int(p1[1] * CAM_H)), (int(p2[0] * CAM_W), int(p2[1] * CAM_H)), color,thickness)# 控制屏幕亮度
def screen_change(percent): # percent/2即为亮度百分比SCREEN = wmi.WMI(namespace='root/WMI')a = SCREEN.WmiMonitorBrightnessMethods()[0]a.WmiSetBrightness(Brightness=percent, Timeout=500)# 初始化音量控制
def init_voice():devices = AudioUtilities.GetSpeakers()interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)volume = cast(interface, POINTER(IAudioEndpointVolume))volume.SetMute(0, None)volume_range = volume.GetVolumeRange()min_volume = volume_range[0]max_volume = volume_range[1]return (min_volume, max_volume), volume# 加载摄像头实例
cap = cv2.VideoCapture(0)
CAM_W = 640
CAM_H = 480
CAM_SCALE = CAM_W / CAM_H# 加载手部关键点识别实例
hand = HandKeyPoint()# 初始化pygame
pygame.init()
# 设置窗口全屏
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("virtual_control_screen")
# 获取当前窗口大小
window_size = list(screen.get_size())# 设置缓冲区
buffer_light = Buffer(10)
buffer_voice = Buffer(10)last_y = 0
last_2_y = 1
last_2_x = 0# 初始化声音控制
voice_range, volume = init_voice()# 设置亮度条参数
bright_bar_length = 300
bright_bar_height = 20
bright_bar_x = 50
bright_bar_y = 100# 设置音量条参数
vol_bar_length = 300
vol_bar_height = 20
vol_bar_x = 50
vol_bar_y = 50# 主循环 每次循环就是对每帧的处理
while True:img_menu = Nonelh_index = -1# 读取摄像头画面success, frame = cap.read()# 将opencv中图片格式的BGR转换为常规的RGBframe = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 镜面反转frame = cv2.flip(frame, 1)# 处理图像res, arr = hand.process(frame)frame = draw_landmark(frame, res)scale = math.hypot((arr[0, 7, 0] - arr[0, 8, 0]),(arr[0, 7, 1] - arr[0, 8, 1]),(arr[0, 7, 2] - arr[0, 8, 2]))# 计算tan值tan = (arr[0, 0, 1] - arr[0, 12, 1]) / (arr[0, 0, 0] - arr[0, 12, 0])# 计算角度angle = np.arctan(tan) * 180 / np.pi# print(angle)if 20 < angle < 90:path = 'resources/menu/light.png'buffer_light.add_positive()buffer_voice.add_negative()# 显示亮度条和亮度刻度值show_brightness = Trueshow_volume = Falseelif -20 > angle > -50:path = 'resources/menu/voice.png'buffer_voice.add_positive()buffer_light.add_negative()# 显示音量条和音量刻度值show_brightness = Falseshow_volume = Trueelse:path = 'resources/menu/menu.png'buffer_light.add_negative()buffer_voice.add_negative()# 不显示刻度值和百分比show_brightness = Falseshow_volume = False# 计算拇指与食指之间的距离dis = math.hypot(int((arr[1, 4, 0] - arr[1, 8, 0]) * CAM_W), int((arr[1, 4, 1] - arr[1, 8, 1]) * CAM_H))# 右手映射时的缩放尺度s = math.hypot((arr[1, 5, 0] - arr[1, 9, 0]), (arr[1, 5, 1] - arr[1, 9, 1]), (arr[1, 5, 2] - arr[1, 9, 2]))# 调节亮度if buffer_light.state:frame = cv2.putText(frame, 'light ready', (10, 35), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 127, 0))frame = draw_line(frame, arr[1, 4], arr[1, 8], thickness=5, color=(255, 188, 66))if dis != 0:# 线性插值,可以理解为将一个区间中的一个值映射到另一区间内light = np.interp(dis, [int(500 * s), int(3000 * s)], (0, 100))# 调节亮度screen_change(light)# 调节声音elif buffer_voice.state:frame = cv2.putText(frame, 'voice ready', (10, 35), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 127, 0))frame = draw_line(frame, arr[1, 4], arr[1, 8], thickness=5, color=(132, 134, 248))if dis != 0:vol = np.interp(dis, [int(500 * s), int(3000 * s)], voice_range)# 调节音量volume.SetMasterVolumeLevel(vol, None)# 将图片改为与窗口一样的大小frame = cv2.resize(frame, (int(window_size[1] * CAM_SCALE), window_size[1]))frame = cv2.transpose(frame)# 渲染图片frame = pygame.surfarray.make_surface(frame)screen.blit(frame, (int(0.5 * (CAM_W - CAM_H * CAM_SCALE)), 0))img_menu = pygame.image.load(path).convert_alpha()img_w, img_h = img_menu.get_size()img_menu = pygame.transform.scale(img_menu, (int(img_w * scale * 5), int(img_h * scale * 5)))x = (arr[0][9][0] + arr[0][13][0] + arr[0][0][0]) / 3y = (arr[0][9][1] + arr[0][13][1] + arr[0][0][1]) / 3x = int(x * window_size[0] - window_size[0] * scale * 3.5)y = int(y * window_size[1] - window_size[1] * scale * 12)# print(x, y)screen.blit(img_menu, (x, y))# 绘制音量条和亮度条的外框if show_volume:pygame.draw.rect(screen, (255, 255, 255), (vol_bar_x, vol_bar_y, vol_bar_length, vol_bar_height), 3)elif show_brightness:pygame.draw.rect(screen, (255, 255, 255), (bright_bar_x, bright_bar_y, bright_bar_length, bright_bar_height),3)# 计算当前音量和亮度在条上的位置和大小,并绘制已填充的条if show_volume:vol = volume.GetMasterVolumeLevel()vol_range = voice_range[1] - voice_range[0]vol_bar_fill_length = int((vol - voice_range[0]) / vol_range * vol_bar_length)pygame.draw.rect(screen, (0, 255, 0), (vol_bar_x, vol_bar_y, vol_bar_fill_length, vol_bar_height))# 显示音量刻度值和当前音量大小vol_text = f"Volume: {int((vol - voice_range[0]) / vol_range * 100)}%"vol_text_surface = pygame.font.SysFont(None, 24).render(vol_text, True, (255, 255, 255))screen.blit(vol_text_surface, (vol_bar_x + vol_bar_length + 10, vol_bar_y))elif show_brightness:brightness = wmi.WMI(namespace='root/WMI').WmiMonitorBrightness()[0].CurrentBrightnessbright_bar_fill_length = int(brightness / 100 * bright_bar_length)pygame.draw.rect(screen, (255, 255, 0), (bright_bar_x, bright_bar_y, bright_bar_fill_length, bright_bar_height))# 显示亮度刻度值和当前亮度大小bright_text = f"Brightness: {brightness}%"bright_text_surface = pygame.font.SysFont(None, 24).render(bright_text, True, (255, 255, 255))screen.blit(bright_text_surface, (bright_bar_x + bright_bar_length + 10, bright_bar_y))pygame.display.flip()# 事件监听 若按q则退出程序for event in pygame.event.get():if event.type == pygame.KEYDOWN:if event.key == pygame.K_q:sys.exit(0)相关文章:
计算机视觉 | OpenCV 实现手势虚拟控制亮度和音量
Hi,大家好,我是半亩花海。在当今科技飞速发展的时代,我们身边充斥着各种智能设备,然而,如何更便捷地与这些设备进行交互却是一个不断被探索的课题。本文将主要介绍一个基于 OpenCV 的手势识别项目,通过手势…...
python28-Python的运算符之三目运算符
Python可通过if语句来实现三目运算符的功能,因此可以近似地把这种if语句当成三目运算符。作为三目运算符的f语句的语法格式如下 True_statements if expression else False_statements 三目运算符的规则是:先对逻辑表达式expression求值,如果逻辑表达式…...
高德 API 10009
问题 笔者使用高德地图所提供的API接口,访问接口报错 {"info":"USERKEY_PLAT_NOMATCH","infocode":"10009","status":"0","sec_code_debug":"d41d8cd98f00b204e9800998ecf8427e"…...
Go 语言中如何大小端字节序?int 转 byte 是如何进行的?
嗨,大家好!我是波罗学。 本文是系列文章 Go 技巧第十五篇,系列文章查看:Go 语言技巧。 我们先看这样一个问题:“Go 语言中,将 byte 转换为 int 时是否涉及字节序(endianness)&#x…...
论文阅读——MP-Former
MP-Former: Mask-Piloted Transformer for Image Segmentation https://arxiv.org/abs/2303.07336 mask2former问题是:相邻层得到的掩码不连续,差别很大 denoising training非常有效地稳定训练时期之间的二分匹配。去噪训练的关键思想是将带噪声的GT坐标…...
JPEG图像的压缩标准(1)
分3个博客详细介绍JPEG图像的压缩标准,包含压缩和解压缩流程,熵编码过程和文件存储格式。 一、JPEG压缩标准概述 JPEG压缩标准由国际标准化组织 (International Organization for Standardization, ISO) 制订,用于静态图像压缩。JPEG标准包…...
数解 transformer 之 self attention transformer 公式整理
句子长度为n;比如2048,或1024,即,一句话最多可以是1024个单词。 1, 位置编码 可知,E是由n个列向量组成的矩阵,每个列向量表示该列号的位置编码向量。 2, 输入向量 加入本句话第一个单词的词嵌入向量是, 第…...
ubuntu22.04@laptop OpenCV Get Started
ubuntu22.04laptop OpenCV Get Started 1. 源由2. 步骤3. 预期&展望4. 参考资料 1. 源由 OpenCV在学校的时候接触过,不过当时专注在物理、研究方面,没有好好的学习下。 这次借后续视频分析刚性需求,对OpenCV做个入门的学习和研读&#…...
【Java】苍穹外卖 Day01
苍穹外卖-day01 课程内容 软件开发整体介绍苍穹外卖项目介绍开发环境搭建导入接口文档Swagger 项目整体效果展示: 管理端-外卖商家使用用户端-点餐用户使用当我们完成该项目的学习,可以培养以下能力: 1. 软件开发整体介绍 作为一名软件开…...
Ivanti Pulse Connect Secure VPN SSRF(CVE-2023-46805)漏洞
免责声明:文章来源互联网收集整理,请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该…...
GPT-4:比ChatGPT3.5好得多,但它有多好你知道么?
GPT-4简介 GPT-4是一款由OpenAI开发的人工智能语言模型,它是ChatGPT3.5的升级版。GPT-4拥有更强大的学习能力、更高的生成质量和更广泛的知识覆盖范围,被誉为人工智能技术的重要突破。 GPT-4与ChatGPT3.5的对比 1. 学习能力 GPT-4采用了更多的神经网…...
测试:JMeter如何获取非json格式的响应参数
JMeter如何获取非json格式的响应参数 在 JMeter 中获取非 JSON 格式的响应参数通常涉及使用后置处理器来提取这些参数。以下是一些常见的方法来获取不同类型的响应数据: 正则表达式提取器: 适用于提取文本、HTML、XML 等格式中的特定文本。使用正则表达…...
2024年刘谦魔术大揭秘,其中竟用到了约瑟夫环?
目录 前言 魔术过程 揭秘过程 结尾 前言 不知道昨天春晚时刘谦的魔术大家看了没有,相信大家跟我一样也很疑惑,所以爆肝一天我得出了结论。如果你觉得还不错的话,记得点赞收藏,分享给更多的朋友看。 魔术过程 整个魔术可以分…...
openssl3.2 - update debian12‘s default openssl to openssl3.2
文章目录 openssl3.2 - update debian12s default openssl to openssl3.2概述笔记回到debian12自带的openssl版本从源码编译安装最新版的openssl配置ssl访问END openssl3.2 - update debian12’s default openssl to openssl3.2 概述 在debian12虚拟机中编译了openssl3.2(ope…...
VUE2和VUE3区别对比一览
## Vue3总结 ### 官方文档 * [Vue3](https://v3.cn.vuejs.org/api/options*data.html) * [Vue2](https://vuejs.bootcss.com/api/) ### Vue3相对于Vue2的语法特性#### 1.获取数据 * vue2 javascript export default {data() {return {name: myName,}},mounted() {console.log(t…...
Linux - updatedb 命令
1. 功能 updatedb 命令用来创建或更新slocate命令所必需的数据库文件。updatedb 命令的执行过程较长,因为在执行时它会遍历整个系统的目录树,并将所有的文件信息写入 slocate 数据库文件中。 补充说明:slocate 本身具有一个数据库ÿ…...
云计算市场分析
目录 一、云计算市场概述 1.1 概述 二、国外云计算厂商 2.1 亚马逊AWS 2.2 微软AzureAzure 2.3 Apple iCloud 三、国内云计算厂商 3.1 阿里云 3.2 腾讯云 3.3 华为云 3.4 百度智能云 一、云计算市场概述 1.1 概述 云计算从出现以来,其发展就非常迅速。以…...
前端JavaScript篇之call() 和 apply() 的区别?
目录 call() 和 apply() 的区别? call() 和 apply() 的区别? 在JavaScript中,call()和apply()都是用来改变函数中this指向的方法,它们的作用是一样的,只是传参的方式不同。 call()方法和apply()方法的第一个参数都是…...
Java设计模式大全:23种常见的设计模式详解(三)
本系列文章简介: 设计模式是在软件开发过程中,经过实践和总结得到的一套解决特定问题的可复用的模板。它是一种在特定情境中经过验证的经验和技巧的集合,可以帮助开发人员设计出高效、可维护、可扩展和可复用的软件系统。设计模式提供了一种在设计和编码过程中的指导,它用于…...
汇编语言程序设计(二)十六位汇编框架、子程序与堆栈
寄存器 如下是16位通用寄存器,存储在cpu硬件中 AX 返回值 AX寄存器分为两部分 AH和AL AH 高8位 存储功能号 AL 低8位 存储返回码 以下是一个AX寄存器应用: mov ax,4c00h 4c给高位AL,00低位AL,16进制要以h结尾 BX CX 计数…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
