opencv实战项目 手势识别-实现尺寸缩放效果

 手势识别系列文章目录

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

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

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

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

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

5.opencv实战项目 手势识别-手部距离测量

6.opencv实战项目 手势识别-实现尺寸缩放效果

未完待续

目录

 手势识别系列文章目录

1.HandTraqckModule模块

2、主模块


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

在这里插入图片描述

代码需要用到opencv   HandTraqckModule模块   mediapipe模块

1.HandTraqckModule模块

如下:

定义 HandDetector 类,用于检测手势并提取相关信息:

class HandDetector:def __init__(self, mode=False, maxHands=2, detectionCon=0.5, minTrackCon=0.5):# 初始化函数,设置参数self.mode = modeself.maxHands = maxHandsself.detectionCon = detectionConself.minTrackCon = minTrackCon# 初始化 Mediapipe 模块和相关对象self.mpHands = mp.solutions.handsself.hands = self.mpHands.Hands(static_image_mode=self.mode, max_num_hands=self.maxHands,min_detection_confidence=self.detectionCon, min_tracking_confidence=self.minTrackCon)self.mpDraw = mp.solutions.drawing_utilsself.tipIds = [4, 8, 12, 16, 20]self.fingers = []self.lmList = []

findHands 函数:在图像中找到手部,并返回手部信息以及绘制的图像。

    def findHands(self, img, draw=True, flipType=True):# 找到手部,并绘制相关信息imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)self.results = self.hands.process(imgRGB)allHands = []# 处理每个检测到的手if self.results.multi_hand_landmarks:for handType, handLms in zip(self.results.multi_handedness, self.results.multi_hand_landmarks):# 提取手部关键点和边界框信息myHand = {}mylmList = []xList = []yList = []for id, lm in enumerate(handLms.landmark):px, py = int(lm.x * w), int(lm.y * h)mylmList.append([px, py])xList.append(px)yList.append(py)# 计算边界框信息xmin, xmax = min(xList), max(xList)ymin, ymax = min(yList), max(yList)boxW, boxH = xmax - xmin, ymax - yminbbox = xmin, ymin, boxW, boxHcx, cy = bbox[0] + (bbox[2] // 2), bbox[1] + (bbox[3] // 2)myHand["lmList"] = mylmListmyHand["bbox"] = bboxmyHand["center"] = (cx, cy)# 根据手的方向进行翻转if flipType:if handType.classification[0].label == "Right":myHand["type"] = "Left"else:myHand["type"] = "Right"else:myHand["type"] = handType.classification[0].labelallHands.append(myHand)# 绘制手部信息if draw:self.mpDraw.draw_landmarks(img, handLms, self.mpHands.HAND_CONNECTIONS)cv2.rectangle(img, (bbox[0] - 20, bbox[1] - 20), (bbox[0] + bbox[2] + 20, bbox[1] + bbox[3] + 20),(255, 0, 255), 2)cv2.putText(img, myHand["type"], (bbox[0] - 30, bbox[1] - 30), cv2.FONT_HERSHEY_PLAIN,2, (255, 0, 255), 2)if draw:return allHands, imgelse:return allHands

fingersUp 函数:检测手指的状态,返回一个列表表示手指是否抬起。

    def fingersUp(self, myHand):# 检测手指状态,返回列表表示手指是否抬起myHandType = myHand["type"]myLmList = myHand["lmList"]if self.results.multi_hand_landmarks:fingers = []# 大拇指if myHandType == "Right":if myLmList[self.tipIds[0]][0] > myLmList[self.tipIds[0] - 1][0]:fingers.append(1)else:fingers.append(0)else:if myLmList[self.tipIds[0]][0] < myLmList[self.tipIds[0] - 1][0]:fingers.append(1)else:fingers.append(0)# 其他四指for id in range(1, 5):if myLmList[self.tipIds[id]][1] < myLmList[self.tipIds[id] - 2][1]:fingers.append(1)else:fingers.append(0)return fingers

findDistance 函数:计算两点间的距离,可选是否在图像上绘制。

    def findDistance(self, p1, p2, img=None):# 计算两点间的距离,可绘制在图像上x1, y1 = p1x2, y2 = p2cx, cy = (x1 + x2) // 2, (y1 + y2) // 2length = math.hypot(x2 - x1, y2 - y1)info = (x1, y1, x2, y2, cx, cy)if img is not None:cv2.circle(img, (x1, y1), 15, (255, 0, 255), cv2.FILLED)cv2.circle(img, (x2, y2), 15, (255, 0, 255), cv2.FILLED)cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), 3)cv2.circle(img, (cx, cy), 15, (255, 0, 255), cv2.FILLED)return length, info, imgelse:return length, info

HandTraqckModule模块整体代码

"""
Hand Tracking Module
"""import cv2
import mediapipe as mp
import mathclass HandDetector:"""Finds Hands using the mediapipe library. Exports the landmarksin pixel format. Adds extra functionalities like finding howmany fingers are up or the distance between two fingers. Alsoprovides bounding box info of the hand found."""def __init__(self, mode=False, maxHands=2, detectionCon=0.5, minTrackCon=0.5):""":param mode: In static mode, detection is done on each image: slower:param maxHands: Maximum number of hands to detect:param detectionCon: Minimum Detection Confidence Threshold:param minTrackCon: Minimum Tracking Confidence Threshold"""self.mode = modeself.maxHands = maxHandsself.detectionCon = detectionConself.minTrackCon = minTrackConself.mpHands = mp.solutions.handsself.hands = self.mpHands.Hands(static_image_mode=self.mode, max_num_hands=self.maxHands,min_detection_confidence=self.detectionCon, min_tracking_confidence = self.minTrackCon)self.mpDraw = mp.solutions.drawing_utilsself.tipIds = [4, 8, 12, 16, 20]self.fingers = []self.lmList = []def findHands(self, img, draw=True, flipType=True):"""Finds hands in a BGR image.:param img: Image to find the hands in.:param draw: Flag to draw the output on the image.:return: Image with or without drawings"""imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)self.results = self.hands.process(imgRGB)allHands = []h, w, c = img.shapeif  self.results.multi_hand_landmarks:for handType,handLms in zip(self.results.multi_handedness,self.results.multi_hand_landmarks):myHand={}## lmListmylmList = []xList = []yList = []for id, lm in enumerate(handLms.landmark):px, py = int(lm.x * w), int(lm.y * h)mylmList.append([px, py])xList.append(px)yList.append(py)## bboxxmin, xmax = min(xList), max(xList)ymin, ymax = min(yList), max(yList)boxW, boxH = xmax - xmin, ymax - yminbbox = xmin, ymin, boxW, boxHcx, cy = bbox[0] + (bbox[2] // 2), \bbox[1] + (bbox[3] // 2)myHand["lmList"] = mylmListmyHand["bbox"] = bboxmyHand["center"] =  (cx, cy)if flipType:if handType.classification[0].label =="Right":myHand["type"] = "Left"else:myHand["type"] = "Right"else:myHand["type"] = handType.classification[0].labelallHands.append(myHand)## drawif draw:self.mpDraw.draw_landmarks(img, handLms,self.mpHands.HAND_CONNECTIONS)cv2.rectangle(img, (bbox[0] - 20, bbox[1] - 20),(bbox[0] + bbox[2] + 20, bbox[1] + bbox[3] + 20),(255, 0, 255), 2)cv2.putText(img,myHand["type"],(bbox[0] - 30, bbox[1] - 30),cv2.FONT_HERSHEY_PLAIN,2,(255, 0, 255),2)if draw:return allHands,imgelse:return allHandsdef findPosition(self, img, handNo=0, draw=True):"""Finds landmarks of a single hand and puts them in a listin pixel format. Also finds the bounding box around the hand.:param img: main image to find hand in:param handNo: hand id if more than one hand detected:param draw: Flag to draw the output on the image.:return: list of landmarks in pixel format; bounding box"""xList = []yList = []bbox = []bboxInfo = []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.shapepx, py = int(lm.x * w), int(lm.y * h)xList.append(px)yList.append(py)self.lmList.append([px, py])if draw:cv2.circle(img, (px, py), 5, (255, 0, 255), cv2.FILLED)xmin, xmax = min(xList), max(xList)ymin, ymax = min(yList), max(yList)boxW, boxH = xmax - xmin, ymax - yminbbox = xmin, ymin, boxW, boxHcx, cy = bbox[0] + (bbox[2] // 2), \bbox[1] + (bbox[3] // 2)bboxInfo = {"id": id, "bbox": bbox, "center": (cx, cy)}if draw:cv2.rectangle(img, (bbox[0] - 20, bbox[1] - 20),(bbox[0] + bbox[2] + 20, bbox[1] + bbox[3] + 20),(0, 255, 0), 2)return self.lmList, bboxInfodef fingersUp(self,myHand):"""Finds how many fingers are open and returns in a list.Considers left and right hands separately:return: List of which fingers are up"""myHandType =myHand["type"]myLmList = myHand["lmList"]if self.results.multi_hand_landmarks:fingers = []# Thumbif myHandType == "Right":if myLmList[self.tipIds[0]][0] > myLmList[self.tipIds[0] - 1][0]:fingers.append(1)else:fingers.append(0)else:if myLmList[self.tipIds[0]][0] < myLmList[self.tipIds[0] - 1][0]:fingers.append(1)else:fingers.append(0)# 4 Fingersfor id in range(1, 5):if myLmList[self.tipIds[id]][1] < myLmList[self.tipIds[id] - 2][1]:fingers.append(1)else:fingers.append(0)return fingersdef findDistance(self,p1, p2, img=None):"""Find the distance between two landmarks based on theirindex numbers.:param p1: Point1:param p2: Point2:param img: Image to draw on.:param draw: Flag to draw the output on the image.:return: Distance between the pointsImage with output drawnLine information"""x1, y1 = p1x2, y2 = p2cx, cy = (x1 + x2) // 2, (y1 + y2) // 2length = math.hypot(x2 - x1, y2 - y1)info = (x1, y1, x2, y2, cx, cy)if img is not None:cv2.circle(img, (x1, y1), 15, (255, 0, 255), cv2.FILLED)cv2.circle(img, (x2, y2), 15, (255, 0, 255), cv2.FILLED)cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), 3)cv2.circle(img, (cx, cy), 15, (255, 0, 255), cv2.FILLED)return length,info, imgelse:return length, infodef main():cap = cv2.VideoCapture(0)detector = HandDetector(detectionCon=0.8, maxHands=2)while True:# Get image framesuccess, img = cap.read()# Find the hand and its landmarkshands, img = detector.findHands(img)  # with draw# hands = detector.findHands(img, draw=False)  # without drawif hands:# Hand 1hand1 = hands[0]lmList1 = hand1["lmList"]  # List of 21 Landmark pointsbbox1 = hand1["bbox"]  # Bounding box info x,y,w,hcenterPoint1 = hand1['center']  # center of the hand cx,cyhandType1 = hand1["type"]  # Handtype Left or Rightfingers1 = detector.fingersUp(hand1)if len(hands) == 2:# Hand 2hand2 = hands[1]lmList2 = hand2["lmList"]  # List of 21 Landmark pointsbbox2 = hand2["bbox"]  # Bounding box info x,y,w,hcenterPoint2 = hand2['center']  # center of the hand cx,cyhandType2 = hand2["type"]  # Hand Type "Left" or "Right"fingers2 = detector.fingersUp(hand2)# Find Distance between two Landmarks. Could be same hand or different handslength, info, img = detector.findDistance(lmList1[8], lmList2[8], img)  # with draw# length, info = detector.findDistance(lmList1[8], lmList2[8])  # with draw# Displaycv2.imshow("Image", img)cv2.waitKey(1)if __name__ == "__main__":main()

2、主模块

原理:

  1. 当检测到两只手时,并且两只手的拇指和食指都抬起时,通过计算拇指指尖之间的距离来获取初始距离 startDist

  2. 当两只手的拇指和食指都抬起时,计算当前拇指指尖之间的距离,并根据距离变化来调整缩放因子 scale。这个变化可以通过当前距离减去初始距离得到。

  3. 根据计算得到的 scale 值,调整图像的尺寸,将另一张图像按照 scale 进行缩放。

这样,当你用两只手的拇指和食指模拟捏取的动作时,可以实现图像的放大和缩小效果。两只手之间的距离越大,图像缩小得越多;两只手之间的距离越小,图像放大得越多。

这个应用可以在许多场景中使用,比如在展示图像、视频播放或地图应用中,通过手势来实现图像的交互式缩放效果。这个示例,展示了手势识别在图像处理和交互中的潜在应用。

导入所需的库:

import cv2
from HandTrackingModule import *

配置摄像头,创建手势检测器对象:

cap = cv2.VideoCapture(0)
cap.set(3, 1280)  # 设置摄像头的宽度
cap.set(4, 720)   # 设置摄像头的高度detector = HandDetector(detectionCon=0.8)  # 创建手势检测器对象,设置检测置信度阈值

定义变量用于手势缩放操作:

startDist = None  # 用于存储初始距离
scale = 0  # 缩放值
cx, cy = 500, 500  # 缩放中心的坐标

进入主循环,读取视频帧并执行手势识别和图像操作:

while True:success, img = cap.read()  # 读取视频帧hands, img = detector.findHands(img)  # 手势检测# 读取一张图像用于操作img1 = cv2.imread("cvarduino.jpg")if len(hands) == 2:# 如果检测到两只手if detector.fingersUp(hands[0]) == [1, 1, 0, 0, 0] and \detector.fingersUp(hands[1]) == [1, 1, 0, 0, 0]:lmList1 = hands[0]["lmList"]  # 第一只手的关键点列表lmList2 = hands[1]["lmList"]  # 第二只手的关键点列表# 计算两个手指尖之间的距离作为缩放参考if startDist is None:length, info, img = detector.findDistance(lmList1[8], lmList2[8], img)startDist = lengthlength, info, img = detector.findDistance(lmList1[8], lmList2[8], img)scale = int((length - startDist) // 2)  # 计算缩放值cx, cy = info[4:]  # 获取缩放中心的坐标print(scale)  # 打印缩放值else:startDist = Nonetry:h1, w1, _ = img1.shapenewH, newW = ((h1 + scale) // 2) * 2, ((w1 + scale) // 2) * 2img1 = cv2.resize(img1, (newW, newH))# 在指定位置绘制缩放后的图像img[cy - newH // 2:cy + newH // 2, cx - newW // 2:cx + newW // 2] = img1except:passcv2.imshow("Image", img)  # 显示处理后的图像cv2.waitKey(1)  # 等待按键

主模块

全部代码:

import cv2
# from cvzone.HandTrackingModule import HandDetector
from HandTrackingModule import *
cap = cv2.VideoCapture(0)
cap.set(3, 1280)
cap.set(4, 720)detector = HandDetector(detectionCon=0.8)
startDist = None
scale = 0
cx, cy = 500,500
while True:success, img = cap.read()hands, img = detector.findHands(img)img1 = cv2.imread("cvarduino.jpg")if len(hands) == 2:# print('Zoom Gesture')# print(detector.fingersUp(hands[0]),detector.fingersUp(hands[1]))if detector.fingersUp(hands[0]) == [1, 1, 0, 0, 0] and \detector.fingersUp(hands[1]) == [1, 1, 0, 0, 0]:# print('zhenque ')lmList1 = hands[0]["lmList"]lmList2 = hands[1]["lmList"]# point 8 is the tip of the index fingerif startDist is None:length, info, img = detector.findDistance(lmList1[8], lmList2[8], img)# print(length)startDist = lengthlength, info, img = detector.findDistance(lmList1[8], lmList2[8], img)scale = int((length - startDist) // 2)cx, cy = info[4:]print(scale)else:startDist = Nonetry:h1, w1, _= img1.shapenewH, newW = ((h1+scale)//2)*2, ((w1+scale)//2)*2img1 = cv2.resize(img1, (newW,newH))img[cy-newH//2:cy+ newH//2, cx-newW//2:cx+ newW//2] = img1except:passcv2.imshow("Image", img)cv2.waitKey(1)

 

有遇到的问题欢迎评论区留言!

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

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

相关文章

基于低代码和数字孪生技术的电力运维平台设计

电力能源服务商在为用能企业提供线上服务的时候&#xff0c;不可避免要面对用能企业的各种个性化需求。如果这些需求和想法都要靠平台厂家研发人员来实现&#xff0c;那在周期、成本、效果上都将是无法满足服务运营需要的&#xff0c;这也是目前很多线上能源云平台应用效果不理…

【状态模式】拯救if-else堆出来的屎山代码

前言 我想大家平时都在开发重都遇见过屎山代码&#xff0c;这些屎山代码一般都是由于复杂且庞大的if-else造成的&#xff0c;状态模式&#xff0c;是一种很好的优化屎山代码的设计模式&#xff0c;本文将采用两个业务场景的示例来讲解如何使用状态模式拯救屎山代码。 目录 前…

【Axure高保真原型】通过输入框动态控制环形图

今天和大家分享通过输入框动态控制环形图的原型模板&#xff0c;在输入框里维护项目数据&#xff0c;可以自动生成对应的环形图&#xff0c;鼠标移入对应扇形&#xff0c;可以查看对应数据。使用也非常方便&#xff0c;只需要修改输入框里的数据&#xff0c;或者复制粘贴文本&a…

简单记录牛客top101算法题(初级题C语言实现)BM17 二分查找 BM21 旋转数组的最小数字 BM23 二叉树的前序遍历

1. BM17 二分查找 要求&#xff1a;给定一个 元素升序的、无重复数字的整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff08;下标从 0 开始&#xff09;&#xff0c;否则返回 -1。 输入&#xff1a…

【云原生】K8S存储卷:PV、PVC详解

目录 一、emptyDir存储卷二、hostPath存储卷三、nfs共享存储卷四、PVC 和 PV4.1 NFS使用PV和PVC4.2创建动态PV 一、emptyDir存储卷 容器磁盘上的文件的生命周期是短暂的&#xff0c;这就使得在容器中运行重要应用时会出现一些问题。首先&#xff0c;当容器崩溃时&#xff0c;ku…

UG NX二次开发(C++)-PK函数创建一条圆弧曲线

文章目录 1、前言2、创建一个项目3、添加头文件4、在do_it中添加创建圆曲线的源代码5、调用dll6、再创建一个长方体验证1、前言 采用PK进行UG NX二次开发,现在看到的文章很多是直接创建实体,然后在UG NX的视图区显示出来,对于创建圆曲线的文章不多,本文讲一下PK函数创建圆…

Git 代码分支规范

目的 俗话说&#xff1a;没有规矩&#xff0c;不成方圆。遵循一个好的规章制度能让你的工作事半功倍。同时也可以展现出你做事的认真的态度以及你的专业性&#xff0c;不会显得杂乱无章&#xff0c;管理困难。Git分支规范也是一样。当遵循了某种约定的Git分支&#xff0c;在代…

若依框架浅浅介绍

由若依官网所给介绍可知 1、文件结构介绍 在ruoyi-admin的pom.xml文件中引入了ruoyi-framework、ruoyi-quartz和ruoyi-generatior模块&#xff0c;在ruoyi-framework的pom.xml文件中引入了ruoyi-system模块。 2、技术栈介绍 前端&#xff1a;Vue、Element UI后端&#xff1a…

第1章:绪论

科学、技术、工程、应用 科学&#xff1a;是什么、为什么技术&#xff1a;怎么做工程&#xff1a;怎样做的多快好省应用&#xff1a;怎么使用 定义 机器学习&#xff1a;利用经验改善系统自身的性能。 研究 智能数据分析&#xff08;数据分析算法&#xff09; 典型的机器…

电脑ip地址怎么改 ip地址怎么改到别的城市

一、ip地址怎么改到别的城市 1.ip地址怎么改到别的城市&#xff0c;1、重启WIFI路由设备 一般手机或电脑在家或公司上网时都是接入到路由器的WIFI网络,再由路由器分配上网IP地址,如果要更换上网IP那么重启路由器设备后,路由器会向网络运营商进行宽带的重新拨号,此时手机或电脑设…

【【verilog 典型电路设计之加法器树乘法器】】

verilog 典型电路设计之加法器树乘法器 加法器树乘法器 加法器树乘法器的设计思想是“移位后加”&#xff0c;并且加法运算采用加法器树的形式。乘法运算的过程是&#xff0c;被乘数与乘数的每一位相乘并且乘以相应的权值&#xff0c;最后将所得的结果相加&#xff0c;便得到了…

selenium.webdriver Python爬虫教程

文章目录 selenium安装和使用 selenium安装和使用 pip install selenium 下载对应的浏览器驱动 实例化浏览器 from selenium import webdriverbrowser webdriver.Chrome()元素定位 控制浏览器

HTB-Keeper

HTB-Keeper 信息收集80端口 lnorgaardroot 信息收集 80端口 80主页给了一个跳转的链接 跟随链接后到了一个登陆界面。 尝试搜索默认密码。 通过账号root:password登录。不知道为什么我登陆了两次才成功。 通过搜索在Admin->Users->Select里面发现了用户信息。 lno…

WS2812B————动/静态显示

一&#xff0c;系统架构 二&#xff0c;芯片介绍 1.管脚说明 2.数据传输时间 3.时序波形 4.数据传输方法 5.常用电路连接 三&#xff0c;代码展示及说明 驱动模块 在驱动模块首先选择使用状态机&#xff0c;其中包括&#xff0c;空闲状态&#xff0c;复位清空状态&#xff0c…

怎么把图片表格转换成word表格?几个步骤达成

在处理文档时&#xff0c;图片表格的转换是一个常见的需求。而手动输入表格是非常耗时的&#xff0c;因此&#xff0c;使用文本识别软件来自动转换图片表格可以大大提高工作效率。在本文中&#xff0c;我们将介绍如何使用OCR文字识别技术来将图片表格转换为Word表格。 OCR文字识…

15.3 【Linux】循环执行的例行性工作调度

相对于 at 是仅执行一次的工作&#xff0c;循环执行的例行性工作调度则是由 cron &#xff08;crond&#xff09; 这个系统服务来控制的。刚刚谈过 Linux 系统上面原本就有非常多的例行性工作&#xff0c;因此这个系统服务是默认启动的。另外&#xff0c; 由于使用者自己也可以…

栈和队列--受限制的线性表

目录 和队列的定义和特点 1.1栈的定义和特点、 1.2队列的定义和特点 1.3栈和队列的应用 2.栈的表示和操作的实现 2.1栈的类型定义 2.2顺序栈的表示和实现 2.2.1初始化 2.2.2入栈 2.2.3出栈 2.2.4取栈顶元素 2.3链栈的表示和实现 2.2.1初始化 2.2.2入栈 2.2.3出栈…

Java-运算符和控制语句(下)(基于c语言的补充)

输出到控制台 System.out.println(msg); // 输出一个字符串, 带换行 System.out.print(msg); // 输出一个字符串, 不带换行 System.out.printf(format, msg); // 格式化输出 从键盘输入 使用 Scanner 读取字符串/整数/浮点数 首先需要导入util包 自动导入util包 这里把回车看…

如何选择最佳的文件传输协议?(FTP、TFTP、Raysync)

在数字化时代&#xff0c;通过互联网传输文件是一项常见的任务。因此&#xff0c;选择适合您企业需求的文件传输协议非常重要。 文件传输协议是发送方和接收方之间的一套规则和信息。它的作用就像网络两端都能理解的一种语言&#xff0c;使得数据可以正确输出并带有正确的文件…

【高频面试题】JVM篇

文章目录 一、JVM组成1.什么是程序计数器2.什么是Java堆&#xff1f;3.能不能介绍一下方法区(元空间&#xff09;4.你听过直接内存吗5.什么是虚拟机栈6.垃圾回收是否涉及栈内存&#xff1f;7.栈内存分配越大越好吗&#xff1f;8.方法内的局部变量是否线程安全&#xff1f;9.什么…