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

手势识别系列文章目录

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

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. 将处理后的图像显示在窗口中,按下任意键退出循环。

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

 

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

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

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2019年9月全国计算机等级考试真题(C语言二级)

2019年9月全国计算机等级考试真题&#xff08;C语言二级&#xff09; 第1题 1、“商品”与“顾客”两个实体集之间的联系一般是 A. 一对一 B. 一对多 C. 多对一 D. 多对多 正确答案&#xff1a;D 第2题 定义学生选修课程的关系模式&#xff1a;SC&#xff08;S#&#xff0c…

.netcore grpc双向流方法详解

一、双向流处理概述 简单来讲客户端可以向服务端发送消息流&#xff0c;服务端也可以向客户端传输响应流&#xff0c;即客户端和服务端可以互相通讯客户端无需发送消息即可开始双向流式处理调用 。 客户端可选择使用 RequestStream.WriteAsync 发送消息。 使用 ResponseStream…

Golang 基础语法问答

使用值为 nil 的 slice、map 会发生什么&#xff1f; 允许对值为 nil 的 slice 添加元素&#xff0c;但是对值为 nil 的 map 添加元素时会造成运行时 panic。 // map错误示例 func main() {var m map[string]intm["one"] 1 // error: panic: assignment to entry …

(5)所有角色数据分析页面的构建-5

所有角色数据分析页面&#xff0c;包括一个时间轴柱状图、六个散点图、六个柱状图(每个属性角色的生命值/防御力/攻击力的max与min的对比)。 """绘图""" from pyecharts.charts import Timeline from find_type import FindType import pandas …

特殊链表(循环单链表,循环双链表,静态链表)

目录 1.循环单链表的初始化 2.循环双链表 3. 静态链表 (1)静态链表的初始化 (2)静态链表的插入 1.循环单链表的初始化 typedef int ElemType; typedef struct LNode{ElemType data;struct LNode *next;}LNode,*LinkList;bool InitList(LinkList &L) {L(LNode*)malloc(…

微服务基础概念【内含图解】

目录 拓展补充&#xff1a; 单体架构 分布式架构 面向服务的体系结构 云原生 微服务架构 什么是微服务&#xff1f; 微服务定义 拓展补充&#xff1a; 单体架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff0c;最终打成一个包部署 优点&#x…

Zabbix-6.4.4 邮箱告警SMS告警配置

目录 ​------------------------- # 邮箱告警 ---------------------------------- 1.安装mailx与postfix软件包 2.修改mailx配置文件 3. 创建文件夹 4. 编写mail-send.sh脚本 5. 将该脚本赋予执行权限 6. 进入web界面进行设置—> Alerts —> Media Types 7. 添…

uniapp小程序实现上传图片功能,并显示上传进度

效果图&#xff1a; 实现方法&#xff1a; 一、通过uni.chooseMedia(OBJECT)方法&#xff0c;拍摄或从手机相册中选择图片或视频。 官方文档链接: https://uniapp.dcloud.net.cn/api/media/video.html#choosemedia uni.chooseMedia({count: 9,mediaType: [image,video],so…

Apache-DBUtils

目录 封装方法 引出dbutils 案例 当关闭connection后&#xff0c;resultset结果集就无法使用了&#xff0c;这就使得resultset不利于数据的管理 封装方法 我们可以将结果集先存储在一个集合中&#xff0c;当connection关闭后&#xff0c;我们可以通过访问集合来访问结果集 …

7.11 Java方法重写

7.11 Java方法重写 这里首先要确定的是重写跟属性没有关系&#xff0c;重写都是方法的重写&#xff0c;与属性无关 带有关键字Static修饰的方法的重写实例 父类实例 package com.baidu.www.oop.demo05;public class B {public static void test(){System.out.println("这…

C++--红黑树

1.什么是红黑树 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路径会比其他路径长出俩倍&#xff0c;因…

【Java转Go】快速上手学习笔记(二)之基础篇一

目录 创建项目数据类型变量常量类型转换计数器键盘交互流程控制代码运算符 创建项目 上篇我们安装好了Go环境&#xff0c;和用IDEA安装Go插件来开发Go项目&#xff1a;【Java转Go】快速上手学习笔记&#xff08;一&#xff09;之环境安装篇 。 这篇我们开始正式学习Go语言。我…

【新知测评实验室】解谜扫描全能王——“智能高清滤镜”黑科技

目录 一、“智能高清滤镜” 原理分析1.1、智能扫描引擎AI-Scan功能拆解1.1.1、**图像感知**1.1.2、场景化决策 1.2、版面还原与识别技术分析1.2.1、元素检测和识别1.2.2、元素聚合1.2.3、版面识别 二、深度测评——“智能高清滤镜”功能2.1、图像处理方面2.2、摩尔纹去除方面2.…

【C++类和对象】类有哪些默认成员函数呢?(下)

文章目录 一、类的6个默认成员函数二、日期类的实现2.1 运算符重载部分2.2 日期之间的运算2.3 整体代码1.Date.h部分2. Date.cpp部分 三. const成员函数四. 取地址及const取地址操作符重载扩展内容 总结 ヾ(๑╹◡╹)&#xff89;" 人总要为过去的懒惰而付出代价ヾ(๑╹◡…

ffmepg滤镜

代码实现&#xff1a; 1.get_format() 这个是QSV硬件解码时的回调函数&#xff0c;在这里初始化hw_frames_ctx, get_format会在解码时被调用。因此对滤镜的初始化init_filter()应在得到第一帧数据后调用。 2.hw_frames_ctx&#xff0c;需要按照要求把他们传给对应的filter 3.然…

向量数据库 Milvus Cloud Partition Key:租户数量多,单个租户数据少的三种解决方案

三种解决方案 这个问题提出的时候,Milvus 的最新版本是 2.2.8,我们做个角色互换,在当时站在这个用户的角度,留在我们面前的选择有这么几个: 为每个租户创建一个 collection 为每个租户创建一个 partition 创建一个租户名称的标量字段 接下来,我们依次分析下这三种方案的可…

OPPO A57刷机资源(附简略教程)

https://www.123pan.com/s/hcAqVv-fpHWd.html提取码:buAp 图中画框的为必须下载的&#xff08;xiaomiflash和twrp必须解压后使用&#xff09; ​ 打开xiaomiflash点击driver点击install&#xff08;就是框住的按钮&#xff09;等待安装完成 ​用数据线将oppo a57与电脑连接&a…

【数学建模】逻辑回归算法(Logistic Resgression)

逻辑回归算法 简介逻辑回归与条件概率绘制sigmoid函数 简介 逻辑回归算法是一种简单但功能强大的二元线性分类算法。需要注意的是&#xff0c;尽管"逻辑回归"名字带有“回归”二字&#xff0c;但逻辑回归是一个分类算法&#xff0c;而不是回归算法。 我认为&#xff…

用easyui DataGrid编辑树形资料

easyui显示编辑树形资料有TreeGrid元件&#xff0c;但是这个元件的vue版本和react版本没有分页功能。virtual scroll功能也表现不佳。 我用DataGrid来处理。要解决的问题点&#xff1a; &#xff08;1&#xff09;如何显示成树形。即&#xff0c;子节点如何有缩进。 先计算好…

一、进入sql环境,以及sql的查询、新建、删除、使用

1、进入sql环境 》》》mysql -u root -p 》》》输入密码 2、sql语言的分类 3、注意事项&#xff1a; 4、基础操作&#xff1a; &#xff08;1&#xff09;查询所有数据库&#xff1a; show databases; 运行结果&#xff1a; &#xff08;2&#xff09;创建一个新的数据库&…