opencv实战项目 手势识别-手势控制鼠标

news2025/2/7 4:18:26

手势识别系列文章目录

手势识别是一种人机交互技术,通过识别人的手势动作,从而实现对计算机、智能手机、智能电视等设备的操作和控制。

1.  opencv实现手部追踪(定位手部关键点)

2.opencv实战项目 实现手势跟踪并返回位置信息(封装调用)

3.手势识别-手势音量控制(opencv)

4.opencv实战项目 手势识别-手势控制鼠标

未完待续

本专栏记录作者的学习之旅会一直更新下去,欢迎订阅一起学习进步


本项目是使用了谷歌开源的框架mediapipe,里面有非常多的模型提供给我们使用,例如面部检测,身体检测,手部检测等

在这里插入图片描述

 

代码需要用到opencv   HandTraqckModule模块   mediapipe模块和一个鼠标控制模块autopy


一、HandTraqckModule模块 

前面的文章中有封装手部检测模块的教程,这边简单的介绍一下

import cv2
import mediapipe as mp
import time

class handDetector():
    def __init__(self, mode=False, maxHands=2, detectionCon=0.5, trackCon=0.5):
        """
        初始化手势检测器对象。

        Args:
            mode (bool): 是否检测多只手。默认为False,只检测单只手。
            maxHands (int): 最多检测的手的数量。默认为2。
            detectionCon (float): 手势检测的置信度阈值。默认为0.5。
            trackCon (float): 手势跟踪的置信度阈值。默认为0.5。
        """
        self.mode = mode
        self.maxHands = maxHands
        self.detectionCon = detectionCon
        self.trackCon = trackCon

        # 创建 Mediapipe Hands 模块和绘制工具对象
        self.mpHands = mp.solutions.hands
        self.hands = self.mpHands.Hands(self.mode, self.maxHands,
                                       self.detectionCon, self.trackCon)
        self.mpDraw = mp.solutions.drawing_utils
        self.tipIds = [4, 8, 12, 16, 20]

    def findHands(self, img, draw=True):
        """
        检测手势并在图像上绘制关键点和连接线。

        Args:
            img (numpy.ndarray): 输入图像。
            draw (bool): 是否在图像上绘制标记。默认为True。

        Returns:
            numpy.ndarray: 绘制了关键点和连接线的图像。
        """
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        self.results = self.hands.process(imgRGB)
        
        if self.results.multi_hand_landmarks:
            for handLms in self.results.multi_hand_landmarks:
                if draw:
                    self.mpDraw.draw_landmarks(img, handLms,
                                               self.mpHands.HAND_CONNECTIONS)
        return img

 

这是第一个小模块,用于创建手势检测器对象以及进行手势检测并在图像上绘制关键点和连接线。下面是对第一个小模块的详细解释:

  1. handDetector 类:定义了手势检测器对象,它具有以下初始化参数和方法。

    • __init__(self, mode=False, maxHands=2, detectionCon=0.5, trackCon=0.5):初始化函数,创建手势检测器对象并设置相关参数。

      • mode:是否检测多只手,默认为False。
      • maxHands:最多检测的手的数量,默认为2。
      • detectionCon:手势检测的置信度阈值,默认为0.5。
      • trackCon:手势跟踪的置信度阈值,默认为0.5。
    • findHands(self, img, draw=True):检测手势并在图像上绘制关键点和连接线。

      • img:输入图像(numpy数组)。
      • draw:是否在图像上绘制标记,默认为True。
    • mpHands:Mediapipe Hands 模块。

    • hands:Hand 模型,用于手势检测。

    • mpDraw:Mediapipe 绘制工具。

    • tipIds:手指末端关键点的ID列表。

  2. findHands 方法:接收输入图像,检测手势,并在图像上绘制关键点和连接线。

    • img:输入图像(numpy数组)。
    • draw:是否在图像上绘制标记,默认为True。
  3. imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB):将BGR格式的图像转换为RGB格式,以便Mediapipe处理。

  4. self.results = self.hands.process(imgRGB):使用Mediapipe Hand模型处理图像,得到手势检测结果。

  5. if self.results.multi_hand_landmarks::如果检测到多只手。

  6. for handLms in self.results.multi_hand_landmarks::遍历每只检测到的手。

  7. self.mpDraw.draw_landmarks(img, handLms, self.mpHands.HAND_CONNECTIONS):在图像上绘制手势关键点和连接线。

  8. 返回绘制了关键点和连接线的图像。

    def findPosition(self, img, handNo=0, draw=True):
        """
        获取手指关键点位置和包围框。

        Args:
            img (numpy.ndarray): 输入图像。
            handNo (int): 指定要分析的手的索引。默认为0,即第一只手。
            draw (bool): 是否在图像上绘制标记。默认为True。

        Returns:
            list: 手指关键点列表。
            tuple: 包围框坐标 (xmin, ymin, xmax, ymax)。
        """
        xList = []
        yList = []
        bbox = []
        self.lmList = []

        if self.results.multi_hand_landmarks:
            myHand = self.results.multi_hand_landmarks[handNo]
            for id, lm in enumerate(myHand.landmark):
                # 获取关键点在图像中的坐标
                h, w, c = img.shape
                cx, cy = int(lm.x * w), int(lm.y * h)
                xList.append(cx)
                yList.append(cy)
                self.lmList.append([id, cx, cy])
                if draw:
                    # 在图像上绘制关键点
                    cv2.circle(img, (cx, cy), 5, (255, 0, 255), cv2.FILLED)

            xmin, xmax = min(xList), max(xList)
            ymin, ymax = min(yList), max(yList)
            bbox = xmin, ymin, xmax, ymax

            if draw:
                # 在图像上绘制包围框
                cv2.rectangle(img, (xmin - 20, ymin - 20), (xmax + 20, ymax + 20),
                              (0, 255, 0), 2)

        return self.lmList, bbox

 

这是第二个小模块,用于获取手指关键点位置和包围框。下面是对第二个小模块的详细解释:

  1. findPosition 方法:在图像上绘制手指关键点,并返回手指关键点的坐标列表以及手的包围框坐标。

    • img:输入图像(numpy数组)。
    • handNo:指定要分析的手的索引,默认为0,即第一只手。
    • draw:是否在图像上绘制标记,默认为True。
  2. xListyList:用于存储手指关键点的 x 和 y 坐标。

  3. bbox:包围框的坐标,用于确定手的位置。

  4. self.lmList:手指关键点的列表,格式为 [id, x, y]。

  5. myHand = self.results.multi_hand_landmarks[handNo]:获取指定索引的手势关键点信息。

  6. for id, lm in enumerate(myHand.landmark)::遍历手的关键点。

  7. h, w, c = img.shape:获取图像的高度、宽度和通道数。

  8. cx, cy = int(lm.x * w), int(lm.y * h):计算关键点在图像中的坐标。

  9. xList.append(cx)yList.append(cy):将坐标添加到列表中。

  10. self.lmList.append([id, cx, cy]):将关键点信息添加到关键点列表中。

  11. if draw::如果绘制标记为True。

  12. cv2.circle(img, (cx, cy), 5, (255, 0, 255), cv2.FILLED):在图像上绘制关键点。

  13. xmin, xmax = min(xList), max(xList)ymin, ymax = min(yList), max(yList):计算包围框的坐标。

  14. bbox = xmin, ymin, xmax, ymax:设置包围框的坐标。

  15. cv2.rectangle(img, (xmin - 20, ymin - 20), (xmax + 20, ymax + 20), (0, 255, 0), 2):在图像上绘制包围框。

  16. 返回手指关键点列表和包围框坐标。

    def fingersUp(self):
        """
        判断手指是否伸展。

        Returns:
            list: 包含每个手指的状态,1表示伸展,0表示弯曲。
        """
        fingers = []

        # 判断拇指是否伸展
        if self.lmList[self.tipIds[0]][1] > self.lmList[self.tipIds[0] - 1][1]:
            fingers.append(1)
        else:
            fingers.append(0)

        # 判断其他手指是否伸展
        for id in range(1, 5):
            if self.lmList[self.tipIds[id]][2] < self.lmList[self.tipIds[id] - 2][2]:
                fingers.append(1)
            else:
                fingers.append(0)

        return fingers

    def findDistance(self, p1, p2, img, draw=True, r=15, t=3):
        """
        计算两个关键点之间的距离。

        Args:
            p1 (int): 第一个关键点的索引。
            p2 (int): 第二个关键点的索引。
            img (numpy.ndarray): 输入图像。
            draw (bool): 是否在图像上绘制标记。默认为True。
            r (int): 圆的半径,用于标记关键点。默认为15。
            t (int): 绘制线条的粗细。默认为3。

        Returns:
            float: 两个关键点之间的距离。
            numpy.ndarray: 绘制了距离标记的图像。
            list: 包含关键点坐标的列表 [x1, y1, x2, y2, cx, cy]。
        """
        x1, y1 = self.lmList[p1][1:]
        x2, y2 = self.lmList[p2][1:]
        cx, cy = (x1 + x2) // 2, (y1 + y2) // 2

        if draw:
            # 在图像上绘制线条和关键点
            cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), t)
            cv2.circle(img, (x1, y1), r, (255, 0, 255), cv2.FILLED)
            cv2.circle(img, (x2, y2), r, (255, 0, 255), cv2.FILLED)
            cv2.circle(img, (cx, cy), r, (0, 0, 255), cv2.FILLED)
        
        # 计算两个关键点之间的距离
        length = math.hypot(x2 - x1, y2 - y1)

        return length, img, [x1, y1, x2, y2, cx, cy]

 

这是第三个小模块,用于判断手指是否伸展以及计算两个关键点之间的距离。下面是对第三个小模块的详细解释:

  1. fingersUp 方法:判断每个手指是否伸展,返回包含手指状态的列表。

    • 返回值:包含每个手指状态的列表,1表示伸展,0表示弯曲。
  2. findDistance 方法:计算两个关键点之间的距离,并在图像上绘制标记。

    • p1p2:两个关键点的索引。
    • img:输入图像(numpy数组)。
    • draw:是否在图像上绘制标记,默认为True。
    • r:圆的半径,用于标记关键点,默认为15。
    • t:绘制线条的粗细,默认为3。
  3. x1, y1 = self.lmList[p1][1:]x2, y2 = self.lmList[p2][1:]:获取两个关键点的坐标。

  4. cx, cy = (x1 + x2) // 2, (y1 + y2) // 2:计算两个关键点的中心坐标。

  5. if draw::如果绘制标记为True。

  6. cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), t):在图像上绘制连接两个关键点的线条。

  7. cv2.circle(img, (x1, y1), r, (255, 0, 255), cv2.FILLED)cv2.circle(img, (x2, y2), r, (255, 0, 255), cv2.FILLED):在两个关键点处绘制实心圆圈,用于标记关键点。

  8. cv2.circle(img, (cx, cy), r, (0, 0, 255), cv2.FILLED):在关键点中心绘制实心圆圈,用于标记距离的中心。

  9. length = math.hypot(x2 - x1, y2 - y1):使用勾股定理计算两个关键点之间的距离。

  10. 返回值:返回计算的距离、绘制了标记的图像和包含关键点坐标的列表 [x1, y1, x2, y2, cx, cy]。

 

完整代码

"""
Hand Tracking Module

"""

import cv2
import mediapipe as mp
import time
import math
import numpy as np

class handDetector():
    def __init__(self, mode=False, maxHands=2, detectionCon=0.5, trackCon=0.5):
        self.mode = mode
        self.maxHands = maxHands
        self.detectionCon = detectionCon
        self.trackCon = trackCon

        self.mpHands = mp.solutions.hands
        self.hands = self.mpHands.Hands(self.mode, self.maxHands,
        self.detectionCon, self.trackCon)
        self.mpDraw = mp.solutions.drawing_utils
        self.tipIds = [4, 8, 12, 16, 20]

    def findHands(self, img, draw=True):
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        self.results = self.hands.process(imgRGB)
        # print(results.multi_hand_landmarks)

        if self.results.multi_hand_landmarks:
            for handLms in self.results.multi_hand_landmarks:
                if draw:
                    self.mpDraw.draw_landmarks(img, handLms,
                    self.mpHands.HAND_CONNECTIONS)

        return img

    def findPosition(self, img, handNo=0, draw=True):
        xList = []
        yList = []
        bbox = []
        self.lmList = []
        if self.results.multi_hand_landmarks:
            myHand = self.results.multi_hand_landmarks[handNo]
            for id, lm in enumerate(myHand.landmark):
                # print(id, lm)
                h, w, c = img.shape
                cx, cy = int(lm.x * w), int(lm.y * h)
                xList.append(cx)
                yList.append(cy)
                # print(id, cx, cy)
                self.lmList.append([id, cx, cy])
                if draw:
                    cv2.circle(img, (cx, cy), 5, (255, 0, 255), cv2.FILLED)

        xmin, xmax = min(xList), max(xList)
        ymin, ymax = min(yList), max(yList)
        bbox = xmin, ymin, xmax, ymax

        if draw:
            cv2.rectangle(img, (xmin - 20, ymin - 20), (xmax + 20, ymax + 20),
            (0, 255, 0), 2)

        return self.lmList, bbox

    def fingersUp(self):
        fingers = []
        # Thumb
        if self.lmList[self.tipIds[0]][1] > self.lmList[self.tipIds[0] - 1][1]:
            fingers.append(1)
        else:
            fingers.append(0)

        # Fingers
        for id in range(1, 5):
            if self.lmList[self.tipIds[id]][2] < self.lmList[self.tipIds[id] - 2][2]:
                fingers.append(1)
            else:
                fingers.append(0)

            # totalFingers = fingers.count(1)

        return fingers

    def findDistance(self, p1, p2, img, draw=True,r=15, t=3):
        x1, y1 = self.lmList[p1][1:]
        x2, y2 = self.lmList[p2][1:]
        cx, cy = (x1 + x2) // 2, (y1 + y2) // 2

        if draw:
            cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), t)
            cv2.circle(img, (x1, y1), r, (255, 0, 255), cv2.FILLED)
            cv2.circle(img, (x2, y2), r, (255, 0, 255), cv2.FILLED)
            cv2.circle(img, (cx, cy), r, (0, 0, 255), cv2.FILLED)
            length = math.hypot(x2 - x1, y2 - y1)

        return length, img, [x1, y1, x2, y2, cx, cy]

def main():
    pTime = 0
    cTime = 0
    cap = cv2.VideoCapture(1)
    detector = handDetector()
    while True:
        success, img = cap.read()
        img = detector.findHands(img)
        lmList, bbox = detector.findPosition(img)
        if len(lmList) != 0:
            print(lmList[4])

        cTime = time.time()
        fps = 1 / (cTime - pTime)
        pTime = cTime

        cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3,
        (255, 0, 255), 3)

        cv2.imshow("Image", img)
        cv2.waitKey(1)

if __name__ == "__main__":
    main()

 

二、主代码

import cv2
import numpy as np
import HandTrackingModule as htm
import time
import autopy

##########################
wCam, hCam = 640, 480
frameR = 100  # Frame Reduction
smoothening = 7
#########################

pTime = 0
plocX, plocY = 0, 0
clocX, clocY = 0, 0

cap = cv2.VideoCapture(0)
cap.set(3, wCam)
cap.set(4, hCam)
detector = htm.handDetector(maxHands=1)
wScr, hScr = autopy.screen.size()
# print(wScr, hScr)

while True:
    # 1. Find hand Landmarks
    success, img = cap.read()
    img = detector.findHands(img)
    lmList, bbox = detector.findPosition(img)
    # 2. Get the tip of the index and middle fingers
    if len(lmList) != 0:
        x1, y1 = lmList[8][1:]
        x2, y2 = lmList[12][1:]
        # print(x1, y1, x2, y2)

    # 3. Check which fingers are up
    fingers = detector.fingersUp()
    # print(fingers)
    cv2.rectangle(img, (frameR, frameR), (wCam - frameR, hCam - frameR),
                  (255, 0, 255), 2)
    # 4. Only Index Finger : Moving Mode
    if fingers[1] == 1 and fingers[2] == 0:
        # 5. Convert Coordinates
        x3 = np.interp(x1, (frameR, wCam - frameR), (0, wScr))
        y3 = np.interp(y1, (frameR, hCam - frameR), (0, hScr))
        # 6. Smoothen Values
        clocX = plocX + (x3 - plocX) / smoothening
        clocY = plocY + (y3 - plocY) / smoothening

        # 7. Move Mouse
        autopy.mouse.move(wScr - clocX, clocY)
        cv2.circle(img, (x1, y1), 15, (255, 0, 255), cv2.FILLED)
        plocX, plocY = clocX, clocY

    # 8. Both Index and middle fingers are up : Clicking Mode
    if fingers[1] == 1 and fingers[2] == 1:
        # 9. Find distance between fingers
        length, img, lineInfo = detector.findDistance(8, 12, img)
        print(length)
        # 10. Click mouse if distance short
        if length < 40:
            cv2.circle(img, (lineInfo[4], lineInfo[5]),
                       15, (0, 255, 0), cv2.FILLED)
            autopy.mouse.click()

    # 11. Frame Rate
    cTime = time.time()
    fps = 1 / (cTime - pTime)
    pTime = cTime
    cv2.putText(img, str(int(fps)), (20, 50), cv2.FONT_HERSHEY_PLAIN, 3,
                (255, 0, 0), 3)
    # 12. Display
    cv2.imshow("Image", img)
    cv2.waitKey(1)

 

下面是代码的主要功能和操作步骤的解释:

  1. 导入所需的库和模块(cv2numpyHandTrackingModuletimeautopy)以及一些配置参数。

  2. 创建摄像头对象 cap,设置摄像头的宽度和高度为 wCamhCam

  3. 创建一个 handDetector 对象 detector,用于检测手势。在这里,我们只使用一个手,所以设置 maxHands=1

  4. 获取屏幕的宽度和高度,以便后面的坐标转换。

  5. 进入一个无限循环,不断处理视频帧。

  6. 在循环中,首先从摄像头获取一帧图像,并调用 detector.findHands 方法来检测手势。然后,调用 detector.findPosition 方法获取手势的关键点坐标和边界框。

  7. 根据检测到的手势关键点,判断手指的状态(是否抬起)。

  8. 绘制一个矩形框作为活动区域,用于移动鼠标。

  9. 当食指抬起而中指不抬起时,进入移动模式。将手势坐标转换为屏幕上的坐标,然后进行平滑处理,最后使用 autopy.mouse.move 方法移动鼠标。

  10. 绘制一个实心圆表示食指的位置,并更新上一次的位置。

  11. 当食指和中指同时抬起时,进入点击模式。计算食指和中指之间的距离,如果距离小于阈值,执行鼠标点击操作。

  12. 计算并显示帧率。

  13. 将处理后的图像显示在窗口中,按下任意键退出循环。

利用摄像头捕获的图像,检测手势,然后根据手指状态来模拟鼠标操作。移动模式下,用食指位置移动鼠标;点击模式下,用食指和中指之间的距离来模拟鼠标点击。这样可以实现通过手势来控制鼠标的功能。

 

需要注意的是,运行代码前,需要将食指放在摄像头前。否则会报错

遇到其他错误,可以评论区留言,大家一起解决

 

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

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

相关文章

vivo手机如何设置一周后的闹钟提醒?

在日常生活和工作中&#xff0c;每个人都要面临各种各样的事情需要去处理&#xff0c;有一些事情是需要当天去完成的&#xff0c;还有一些任务是需要提前知晓&#xff0c;做好准确&#xff0c;在未来的指定日期去完成的。例如一周后交付项目资料、10天后提交月度工作总结&#…

高忆管理:股票买了后怎么卖?

股票作为一种出资东西&#xff0c;招引了许多出资者的爱好。然而&#xff0c;关于许多新手出资者来说&#xff0c;他们可能会犯一个常见的过错&#xff0c;就是在购买股票后不知道怎么卖出。本文将从多个视点剖析这个问题&#xff0c;为出资者供给一些有用的建议和指导。 首要&…

机器学习深度学习——注意力提示、注意力池化(核回归)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——常见循环神经网络结构&#xff08;RNN、LSTM、GRU&#xff09; &#x1f4da;订阅专栏&#xff1a;机器…

c刷题(二)

目录 加减混合运算 计算n的k次方 计算非负整数各位之和 字符串逆序 双指针 递归 矩阵计算 矩阵转置 加减混合运算 题目&#xff1a;计算1 / 1 - 1 / 2 1 / 3 - 1 / 4 1 / 5 …… 1 / 99 - 1 / 100 的值&#xff0c;打印出结果。 一般情况我们可以写个循环然后在用条…

pgAdmin开发工具之ERD

pgAdmin 是一个免费的 PostgreSQL 管理与开发平台&#xff0c;这篇文章介绍了它的安装与使用。 今天我们要介绍的是它的一个开发功能&#xff1a;实体关系图&#xff08;ERD&#xff09;工具。 ERD 工具可以使用图形化的方式表示数据库中的表、字段以及表之间的关系。 pgAdmin…

代数学与理论物理中常见的群

代数学与理论物理中常见的群 代数学与理论物理中常见的群 四阶群 六阶群 对称群 二维转动群 三维转动群 三维正交群 群 O3群

【使用go开发区块链】之获取链上数据(03)

上篇文章&#xff0c;我们完成了数据库的连接&#xff0c;本章节&#xff0c;我们将完成ethclient的配置以及初始化 1、ethclient配置 1.1、安装go-ethereum 在命令行终端输入下面代码安装&#xff1a; go get github.com/ethereum/go-ethereum1.2、Ethclient配置 1.2.1、新…

在Qt中使用LoadLibrary无法加载DLL

Qt系列文章目录 文章目录 Qt系列文章目录前言一、问题分析 前言 最近因项目需要使用qt做开发&#xff0c;之前使用LoadLibrary加载dll成功&#xff0c;很庆幸&#xff0c;当一切都那么顺风顺水的时候&#xff0c;测试同事却发现&#xff0c;在windows平台上个别电脑上加载dll会…

百度智能云:千帆大模型平台接入Llama 2等33个大模型,上线103个Prompt模板

大家好&#xff0c;我是herosunly。985院校硕士毕业&#xff0c;现担任算法研究员一职&#xff0c;热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名&#xff0c;CCF比赛第二名&#xff0c;科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的…

LeetCode_03Java_1572. 矩阵对角线元素的和

给你一个正方形矩阵 mat&#xff0c;请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 输入&#xff1a;mat [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;25 解释&#xff1a;对角线的和为&#xff1a;1 5 9 3 7 2…

构建高效外卖系统平台:从需求到实现

随着科技的不断进步和人们生活节奏的加快&#xff0c;外卖成为了越来越多人的饮食选择。为了满足这一需求&#xff0c;开发一套高效的外卖系统平台变得尤为重要。本文将从需求分析开始&#xff0c;逐步引导您了解如何开发一套完整的外卖系统平台。 第一步&#xff1a;需求分析…

3分钟自建查分系统?现在每个人都可以实现了

学生成绩查询系统在现代教育管理中扮演着重要的角色&#xff0c;它不仅可以方便学生和家长查询成绩&#xff0c;也能帮助老师更好地管理和分析学生的学业表现。作为一名教师&#xff0c;了解如何制作学生成绩查询系统是提高教学效率和管理学生成绩便利性的关键。 在制作学生成…

Go 语言并发编程 及 进阶与依赖管理

1.0 从并发编程本质了解Go高性能的本质 1.1 Goroutine 协程可以理解为轻量级线程&#xff1b; Go更适合高并发场景原因之一&#xff1a;Go语言一次可以创建上万协成&#xff1b; “快速”&#xff1a;开多个协成 打印。 go func(): 在函数前加 go 代表 创建协程; time.Sleep():…

Redis心跳检测

在命令传播阶段&#xff0c;从服务器默认会以每秒一次的频率&#xff0c;向主服务器发送命令&#xff1a; REPLCON FACK <rep1 ication_ offset>其中replication_offset是从服务器当前的复制偏移量。 发送REPLCONF ACK命令对于主从服务器有三个作用&#xff1a; 检测主…

坑爹的 InsCode 删我文件

我担心的问题再次发生了&#xff0c;和当初用码云时一样&#xff0c;删我代码删我文件 唉&#xff0c;算求了&#xff0c;还是用自己的网络记事本算了。

人工智能讲师AIGC讲师叶梓:大模型这么火,我们在使用时应该关注些什么?

以下为叶老师讲义分享&#xff1a; P2-P5 大语言模型的演进 开山鼻祖&#xff1a;Transformer 常见的大模型 我们应该关注些什么&#xff1f; 事实描述的正确性2、知识的时效性3、理解、运用语言的能力4、上下文连贯性5、抗干扰&#xff08;误导&#xff09;性能6、无害性7、…

临时文档2

java 中 IO 流分为几种? 按照流的流向分&#xff0c;可以分为输入流和输出流&#xff1b;按照操作单元划分&#xff0c;可以划分为字节流和字符流&#xff1b;按照流的角色划分为节点流和处理流。 Java Io流共涉及40多个类&#xff0c;这些类看上去很杂乱&#xff0c;但实际…

Docker 大热,还不了解 Dockerfile 你就OUT啦~

♥ 前 言 前言&#xff1a;近年来 Docker 非常火&#xff0c;想要玩好 Docker 的话 Dockerfile 是绕不开的&#xff0c;这就好比想要玩好 Linux 服务器绕不开 shell 道理是一样的。今天我们就来聊一聊 Dockerfile 怎么写&#xff0c;那些指令到底是什么意思。 一、先来看一…

NIDS网络威胁检测系统-Golang

使用技术&#xff1a; Golang Gin框架 前端三件套 演示画面&#xff1a; 可以部署在linux和window上 目前已在Kali2021和Window10上进行测试成功

openGauss学习笔记-37 openGauss 高级数据管理-事务

文章目录 openGauss学习笔记-37 openGauss 高级数据管理-事务37.1 语法格式37.2 参数说明37.3 示例 openGauss学习笔记-37 openGauss 高级数据管理-事务 事务是用户定义的一个数据库操作序列&#xff0c;这些操作要么全做要么全不做&#xff0c;是一个不可分割的工作单位。ope…