|
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "initial_id",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2024-09-07T05:11:28.761076Z",
|
|
"start_time": "2024-09-07T05:11:22.404354Z"
|
|
},
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import cv2\n",
|
|
"import time\n",
|
|
"import mediapipe\n",
|
|
"import numpy as np\n",
|
|
"from collections import deque\n",
|
|
"from filterpy.kalman import KalmanFilter"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "40aada17ccd31fe",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2024-09-07T05:11:28.777139Z",
|
|
"start_time": "2024-09-07T05:11:28.761076Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"gesture_locked = {'Left':False,'Right':False}\n",
|
|
"gesture_start_time = {'Left':0,'Right':0}\n",
|
|
"buffer_start_time = {'Left':0,'Right':0}\n",
|
|
"start_drag_time = {'Left':0,'Right':0}\n",
|
|
"dragging = {'Left':False,'Right':False}\n",
|
|
"drag_point = {'Left':(0, 0),'Right':(0, 0)}\n",
|
|
"buffer_duration = {'Left':0.25,'Right':0.25}\n",
|
|
"is_index_finger_up = {'Left':False,'Right':False}\n",
|
|
"index_finger_second = {'Left':0,'Right':0}\n",
|
|
"index_finger_tip = {'Left':0,'Right':0}\n",
|
|
"trajectory = {'Left':[],'Right':[]}\n",
|
|
"square_queue = deque()\n",
|
|
"wait_time = 1.5\n",
|
|
"kalman_wait_time = 0.5\n",
|
|
"wait_box = 2\n",
|
|
"rect_draw_time = {'Left':0,'Right':0}\n",
|
|
"last_drawn_box = {'Left':None,'Right':None}\n",
|
|
"elapsed_time = {'Left':0,'Right':0}"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "2ee9323bb1c25cc0",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2024-09-07T05:11:28.824573Z",
|
|
"start_time": "2024-09-07T05:11:28.777139Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def clear_hand_states(detected_hand ='Both'):\n",
|
|
" global gesture_locked, gesture_start_time, buffer_start_time, dragging, drag_point, buffer_duration,is_index_finger_up, trajectory,wait_time,kalman_wait_time, start_drag_time, rect_draw_time, last_drawn_box, wait_box, elapsed_time\n",
|
|
" \n",
|
|
" hands_to_clear = {'Left', 'Right'}\n",
|
|
" if detected_hand == 'Both':\n",
|
|
" hands_to_clear = hands_to_clear\n",
|
|
" else:\n",
|
|
" hands_to_clear -= {detected_hand}\n",
|
|
" # 反向判断左右手\n",
|
|
"\n",
|
|
" for h in hands_to_clear:\n",
|
|
" gesture_locked[h] = False\n",
|
|
" gesture_start_time[h] = 0\n",
|
|
" buffer_start_time[h] = 0\n",
|
|
" dragging[h] = False\n",
|
|
" drag_point[h] = (0, 0)\n",
|
|
" buffer_duration[h] = 0.25\n",
|
|
" is_index_finger_up[h] = False\n",
|
|
" trajectory[h].clear()\n",
|
|
" start_drag_time[h] = 0\n",
|
|
" rect_draw_time[h] = 0\n",
|
|
" last_drawn_box[h] = None\n",
|
|
" elapsed_time[h] = 0\n",
|
|
" # 清空没被检测的手"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "96cf431d2562e7d",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2024-09-07T05:11:28.855831Z",
|
|
"start_time": "2024-09-07T05:11:28.824573Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"kalman_filters = {\n",
|
|
" 'Left': KalmanFilter(dim_x=4, dim_z=2),\n",
|
|
" 'Right': KalmanFilter(dim_x=4, dim_z=2)\n",
|
|
"}\n",
|
|
"\n",
|
|
"for key in kalman_filters:\n",
|
|
" kalman_filters[key].x = np.array([0., 0., 0., 0.])\n",
|
|
" kalman_filters[key].F = np.array([[1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]])\n",
|
|
" # 状态转移矩阵\n",
|
|
" kalman_filters[key].H = np.array([[1, 0, 0, 0], [0, 1, 0, 0]])\n",
|
|
" # 观测矩阵\n",
|
|
" kalman_filters[key].P *= 1000.\n",
|
|
" kalman_filters[key].R = 3\n",
|
|
" kalman_filters[key].Q = np.eye(4) * 0.01\n",
|
|
"\n",
|
|
"def kalman_filter_point(hand_label, x, y):\n",
|
|
" kf = kalman_filters[hand_label]\n",
|
|
" kf.predict()\n",
|
|
" kf.update([x, y])\n",
|
|
" # 更新状态\n",
|
|
" return (kf.x[0], kf.x[1])\n",
|
|
"\n",
|
|
"def reset_kalman_filter(hand_label, x, y):\n",
|
|
" kf = kalman_filters[hand_label]\n",
|
|
" kf.x = np.array([x, y, 0., 0.])\n",
|
|
" kf.P *= 1000.\n",
|
|
" # 重置"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "edc274b7ed495122",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2024-09-07T05:11:28.887346Z",
|
|
"start_time": "2024-09-07T05:11:28.855831Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"mp_hands = mediapipe.solutions.hands\n",
|
|
"\n",
|
|
"hands = mp_hands.Hands(\n",
|
|
" static_image_mode=False,\n",
|
|
" max_num_hands=2,\n",
|
|
" # 一只更稳定\n",
|
|
" min_detection_confidence=0.5,\n",
|
|
" min_tracking_confidence=0.5\n",
|
|
")\n",
|
|
"\n",
|
|
"mp_drawing = mediapipe.solutions.drawing_utils\n",
|
|
"clear_hand_states()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "51ff809ecaf1f899",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2024-09-07T05:11:28.934274Z",
|
|
"start_time": "2024-09-07T05:11:28.887346Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def process_image(image):\n",
|
|
"\n",
|
|
" start_time = time.time()\n",
|
|
" height, width = image.shape[:2]\n",
|
|
" image = cv2.flip(image, 1)\n",
|
|
" image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
|
|
" # 预处理帧\n",
|
|
" \n",
|
|
" results = hands.process(image)\n",
|
|
" \n",
|
|
" if results.multi_hand_landmarks:\n",
|
|
" # 如果检测到手\n",
|
|
" \n",
|
|
" handness_str = ''\n",
|
|
" index_finger_tip_str = ''\n",
|
|
" \n",
|
|
" if len(results.multi_hand_landmarks) == 1:\n",
|
|
" clear_hand_states(detected_hand = results.multi_handedness[0].classification[0].label)\n",
|
|
" # 如果只有一只手 则清空另一只手的数据 避免后续冲突导致不稳定\n",
|
|
" \n",
|
|
" for hand_idx in range(len(results.multi_hand_landmarks)):\n",
|
|
" \n",
|
|
" hand_21 = results.multi_hand_landmarks[hand_idx]\n",
|
|
" mp_drawing.draw_landmarks(image, hand_21, mp_hands.HAND_CONNECTIONS)\n",
|
|
" \n",
|
|
" temp_handness = results.multi_handedness[hand_idx].classification[0].label\n",
|
|
" handness_str += '{}:{}, '.format(hand_idx, temp_handness)\n",
|
|
" is_index_finger_up[temp_handness] = False\n",
|
|
" # 先设置为false 防止放下被错误更新为竖起\n",
|
|
" \n",
|
|
" cz0 = hand_21.landmark[0].z\n",
|
|
" index_finger_second[temp_handness] = hand_21.landmark[7]\n",
|
|
" index_finger_tip[temp_handness] = hand_21.landmark[8]\n",
|
|
" # 食指指尖和第一个关节\n",
|
|
" \n",
|
|
" index_x, index_y = int(index_finger_tip[temp_handness].x * width), int(index_finger_tip[temp_handness].y * height)\n",
|
|
"\n",
|
|
" if all(index_finger_second[temp_handness].y < hand_21.landmark[i].y for i in range(21) if i not in [7, 8]) and index_finger_tip[temp_handness].y < index_finger_second[temp_handness].y:\n",
|
|
" is_index_finger_up[temp_handness] = True\n",
|
|
" # 如果指尖和第二个关节高度大于整只手所有关节点 则视为执行“指向”操作 \n",
|
|
"\n",
|
|
" if is_index_finger_up[temp_handness]:\n",
|
|
" if not gesture_locked[temp_handness]:\n",
|
|
" if gesture_start_time[temp_handness] == 0:\n",
|
|
" gesture_start_time[temp_handness] = time.time()\n",
|
|
" # 记录食指抬起的时间\n",
|
|
" elif time.time() - gesture_start_time[temp_handness] > wait_time:\n",
|
|
" dragging[temp_handness] = True\n",
|
|
" gesture_locked[temp_handness] = True\n",
|
|
" drag_point[temp_handness] = (index_x, index_y)\n",
|
|
" # 如果食指抬起的时间大于预设的等待时间则视为执行“指向”操作\n",
|
|
" buffer_start_time[temp_handness] = 0\n",
|
|
" # 检测到食指竖起就刷新缓冲时间\n",
|
|
" else:\n",
|
|
" if buffer_start_time[temp_handness] == 0:\n",
|
|
" buffer_start_time[temp_handness] = time.time()\n",
|
|
" elif time.time() - buffer_start_time[temp_handness] > buffer_duration[temp_handness]:\n",
|
|
" gesture_start_time[temp_handness] = 0\n",
|
|
" gesture_locked[temp_handness] = False\n",
|
|
" dragging[temp_handness] = False\n",
|
|
" # 如果缓冲时间大于设定 就证明已经结束指向操作\n",
|
|
" # 这样可以防止某一帧识别有误导致指向操作被错误清除\n",
|
|
" \n",
|
|
" if dragging[temp_handness]:\n",
|
|
"\n",
|
|
" if start_drag_time[temp_handness] == 0:\n",
|
|
" start_drag_time[temp_handness] = time.time()\n",
|
|
" reset_kalman_filter(temp_handness, index_x, index_y)\n",
|
|
" # 每次画线的时候初始化滤波器\n",
|
|
" \n",
|
|
" smooth_x, smooth_y = kalman_filter_point(temp_handness, index_x, index_y)\n",
|
|
" drag_point[temp_handness] = (index_x, index_y)\n",
|
|
" index_finger_radius = max(int(10 * (1 + (cz0 - index_finger_tip[temp_handness].z) * 5)), 0)\n",
|
|
" cv2.circle(image, drag_point[temp_handness], index_finger_radius, (0, 0, 255), -1)\n",
|
|
" # 根据离掌根的深度距离来构建一个圆\n",
|
|
" # 用来显示已经开始指向操作\n",
|
|
" # 和下方构建的深度点位对应 直接用倍数\n",
|
|
" drag_point_smooth = (smooth_x, smooth_y)\n",
|
|
" \n",
|
|
" if time.time() - start_drag_time[temp_handness] > kalman_wait_time:\n",
|
|
" trajectory[temp_handness].append(drag_point_smooth)\n",
|
|
" # 因为kalman滤波器初始化的时候会很不稳定 前几帧通常会有较为严重的噪声\n",
|
|
" # 所以直接等待前几帧运行完成之后再将点位加到轨迹列表中\n",
|
|
" else:\n",
|
|
" if len(trajectory[temp_handness]) > 4:\n",
|
|
" contour = np.array(trajectory[temp_handness], dtype=np.int32)\n",
|
|
" rect = cv2.minAreaRect(contour)\n",
|
|
" box = cv2.boxPoints(rect)\n",
|
|
" box = np.int64(box)\n",
|
|
" rect_draw_time[temp_handness] = time.time()\n",
|
|
" last_drawn_box[temp_handness] = box\n",
|
|
" # 如果指向操作结束 轨迹列表有至少四个点的时候\n",
|
|
" # 使用最小包围图形将画的不规则图案调整为一个矩形\n",
|
|
"\n",
|
|
" start_drag_time[temp_handness] = 0\n",
|
|
" trajectory[temp_handness].clear()\n",
|
|
"\n",
|
|
" for i in range(1, len(trajectory[temp_handness])):\n",
|
|
"\n",
|
|
" pt1 = (int(trajectory[temp_handness][i-1][0]), int(trajectory[temp_handness][i-1][1]))\n",
|
|
" pt2 = (int(trajectory[temp_handness][i][0]), int(trajectory[temp_handness][i][1]))\n",
|
|
" cv2.line(image, pt1, pt2, (0, 0, 255), 2)\n",
|
|
" # 绘制连接轨迹点的线\n",
|
|
"\n",
|
|
" if last_drawn_box[temp_handness] is not None:\n",
|
|
" elapsed_time[temp_handness] = time.time() - rect_draw_time[temp_handness]\n",
|
|
" \n",
|
|
" if elapsed_time[temp_handness] < wait_box:\n",
|
|
" cv2.drawContours(image, [last_drawn_box[temp_handness]], 0, (0, 255, 0), 2)\n",
|
|
" # 将矩形框保留一段时间 否则一帧太快 无法看清效果\n",
|
|
" \n",
|
|
" elif elapsed_time[temp_handness] >= wait_box - 0.1:\n",
|
|
" \n",
|
|
" box = last_drawn_box[temp_handness]\n",
|
|
" x_min = max(0, min(box[:, 0]))\n",
|
|
" y_min = max(0, min(box[:, 1]))\n",
|
|
" x_max = min(image.shape[1], max(box[:, 0]))\n",
|
|
" y_max = min(image.shape[0], max(box[:, 1]))\n",
|
|
" cropped_image = image[y_min:y_max, x_min:x_max]\n",
|
|
" filename = f\"../image/cropped_{temp_handness}_{int(time.time())}.jpg\"\n",
|
|
" cv2.imwrite(filename, cropped_image)\n",
|
|
" last_drawn_box[temp_handness] = None\n",
|
|
" # 不能直接剪裁画完的图像 可能会错误的将手剪裁进去\n",
|
|
" # 等待一段时间 有一个给手缓冲移动走的时间再将这一帧里的矩形提取出来\n",
|
|
" \n",
|
|
" for i in range(21):\n",
|
|
" \n",
|
|
" cx = int(hand_21.landmark[i].x * width)\n",
|
|
" cy = int(hand_21.landmark[i].y * height)\n",
|
|
" cz = hand_21.landmark[i].z\n",
|
|
" depth_z = cz0 - cz\n",
|
|
" radius = max(int(6 * (1 + depth_z*5)), 0)\n",
|
|
" \n",
|
|
" if i == 0:\n",
|
|
" image = cv2.circle(image, (cx, cy), radius, (255, 255, 0), thickness=-1)\n",
|
|
" if i == 8:\n",
|
|
" image = cv2.circle(image, (cx, cy), radius, (255, 165, 0), thickness=-1)\n",
|
|
" index_finger_tip_str += '{}:{:.2f}, '.format(hand_idx, depth_z)\n",
|
|
" if i in [1,5,9,13,17]: \n",
|
|
" image = cv2.circle(image, (cx, cy), radius, (0, 0, 255), thickness=-1)\n",
|
|
" if i in [2,6,10,14,18]:\n",
|
|
" image = cv2.circle(image, (cx, cy), radius, (75, 0, 130), thickness=-1)\n",
|
|
" if i in [3,7,11,15,19]:\n",
|
|
" image = cv2.circle(image, (cx, cy), radius, (238, 130, 238), thickness=-1)\n",
|
|
" if i in [4,12,16,20]:\n",
|
|
" image = cv2.circle(image, (cx, cy), radius, (0, 255, 255), thickness=-1)\n",
|
|
" # 提取出每一个关节点 赋予对应的颜色和根据掌根的深度\n",
|
|
" \n",
|
|
" scaler= 1\n",
|
|
" image = cv2.putText(image,handness_str, (25*scaler, 100*scaler), cv2.FONT_HERSHEY_SIMPLEX, 1.25*scaler, (0,0,255), 2,)\n",
|
|
" image = cv2.putText(image,index_finger_tip_str, (25*scaler, 150*scaler), cv2.FONT_HERSHEY_SIMPLEX, 1.25*scaler, (0,0,255), 2,)\n",
|
|
"\n",
|
|
" spend_time = time.time() - start_time\n",
|
|
" if spend_time > 0:\n",
|
|
" FPS = 1.0 / spend_time\n",
|
|
" else:\n",
|
|
" FPS = 0\n",
|
|
" \n",
|
|
" image = cv2.putText(image,'FPS '+str(int(FPS)),(25*scaler,50*scaler),cv2.FONT_HERSHEY_SIMPLEX,1.25*scaler,(0,0,255),2,)\n",
|
|
" # 显示FPS 检测到的手和食指指尖对于掌根的深度值\n",
|
|
" \n",
|
|
" else:\n",
|
|
" clear_hand_states()\n",
|
|
" # 如果没检测到手就清空全部信息\n",
|
|
" \n",
|
|
" return image"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "b7ce23e80ed36041",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2024-09-07T05:19:32.248575Z",
|
|
"start_time": "2024-09-07T05:11:28.934663Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"C:\\Users\\25055\\AppData\\Local\\Temp\\ipykernel_4200\\752492595.py:89: DeprecationWarning: `np.int0` is a deprecated alias for `np.intp`. (Deprecated NumPy 1.24)\n",
|
|
" box = np.int0(box)\n"
|
|
]
|
|
},
|
|
{
|
|
"ename": "KeyboardInterrupt",
|
|
"evalue": "",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
|
"\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
|
|
"Cell \u001b[1;32mIn[7], line 10\u001b[0m\n\u001b[0;32m 7\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCamera Error\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m 8\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[1;32m---> 10\u001b[0m frame \u001b[38;5;241m=\u001b[39m \u001b[43mprocess_image\u001b[49m\u001b[43m(\u001b[49m\u001b[43mframe\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 11\u001b[0m cv2\u001b[38;5;241m.\u001b[39mimshow(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mVideo\u001b[39m\u001b[38;5;124m'\u001b[39m, frame)\n\u001b[0;32m 13\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m cv2\u001b[38;5;241m.\u001b[39mwaitKey(\u001b[38;5;241m1\u001b[39m) \u001b[38;5;241m&\u001b[39m \u001b[38;5;241m0xFF\u001b[39m \u001b[38;5;241m==\u001b[39m \u001b[38;5;28mord\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mq\u001b[39m\u001b[38;5;124m'\u001b[39m):\n",
|
|
"Cell \u001b[1;32mIn[6], line 9\u001b[0m, in \u001b[0;36mprocess_image\u001b[1;34m(image)\u001b[0m\n\u001b[0;32m 6\u001b[0m image \u001b[38;5;241m=\u001b[39m cv2\u001b[38;5;241m.\u001b[39mcvtColor(image, cv2\u001b[38;5;241m.\u001b[39mCOLOR_BGR2RGB)\n\u001b[0;32m 7\u001b[0m \u001b[38;5;66;03m# 预处理帧\u001b[39;00m\n\u001b[1;32m----> 9\u001b[0m results \u001b[38;5;241m=\u001b[39m \u001b[43mhands\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mprocess\u001b[49m\u001b[43m(\u001b[49m\u001b[43mimage\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 11\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m results\u001b[38;5;241m.\u001b[39mmulti_hand_landmarks:\n\u001b[0;32m 12\u001b[0m \u001b[38;5;66;03m# 如果检测到手\u001b[39;00m\n\u001b[0;32m 14\u001b[0m handness_str \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m'\u001b[39m\n",
|
|
"File \u001b[1;32md:\\app-install-dict\\Anaconda3\\envs\\software_engineering\\lib\\site-packages\\mediapipe\\python\\solutions\\hands.py:153\u001b[0m, in \u001b[0;36mHands.process\u001b[1;34m(self, image)\u001b[0m\n\u001b[0;32m 132\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mprocess\u001b[39m(\u001b[38;5;28mself\u001b[39m, image: np\u001b[38;5;241m.\u001b[39mndarray) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m NamedTuple:\n\u001b[0;32m 133\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Processes an RGB image and returns the hand landmarks and handedness of each detected hand.\u001b[39;00m\n\u001b[0;32m 134\u001b[0m \n\u001b[0;32m 135\u001b[0m \u001b[38;5;124;03m Args:\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 150\u001b[0m \u001b[38;5;124;03m right hand) of the detected hand.\u001b[39;00m\n\u001b[0;32m 151\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[1;32m--> 153\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43msuper\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mprocess\u001b[49m\u001b[43m(\u001b[49m\u001b[43minput_data\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m{\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mimage\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mimage\u001b[49m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\n",
|
|
"File \u001b[1;32md:\\app-install-dict\\Anaconda3\\envs\\software_engineering\\lib\\site-packages\\mediapipe\\python\\solution_base.py:335\u001b[0m, in \u001b[0;36mSolutionBase.process\u001b[1;34m(self, input_data)\u001b[0m\n\u001b[0;32m 329\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 330\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_graph\u001b[38;5;241m.\u001b[39madd_packet_to_input_stream(\n\u001b[0;32m 331\u001b[0m stream\u001b[38;5;241m=\u001b[39mstream_name,\n\u001b[0;32m 332\u001b[0m packet\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_make_packet(input_stream_type,\n\u001b[0;32m 333\u001b[0m data)\u001b[38;5;241m.\u001b[39mat(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_simulated_timestamp))\n\u001b[1;32m--> 335\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_graph\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwait_until_idle\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 336\u001b[0m \u001b[38;5;66;03m# Create a NamedTuple object where the field names are mapping to the graph\u001b[39;00m\n\u001b[0;32m 337\u001b[0m \u001b[38;5;66;03m# output stream names.\u001b[39;00m\n\u001b[0;32m 338\u001b[0m solution_outputs \u001b[38;5;241m=\u001b[39m collections\u001b[38;5;241m.\u001b[39mnamedtuple(\n\u001b[0;32m 339\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mSolutionOutputs\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_output_stream_type_info\u001b[38;5;241m.\u001b[39mkeys())\n",
|
|
"\u001b[1;31mKeyboardInterrupt\u001b[0m: "
|
|
]
|
|
},
|
|
{
|
|
"ename": "",
|
|
"evalue": "",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[1;31m在当前单元格或上一个单元格中执行代码时 Kernel 崩溃。\n",
|
|
"\u001b[1;31m请查看单元格中的代码,以确定故障的可能原因。\n",
|
|
"\u001b[1;31m单击<a href='https://aka.ms/vscodeJupyterKernelCrash'>此处</a>了解详细信息。\n",
|
|
"\u001b[1;31m有关更多详细信息,请查看 Jupyter <a href='command:jupyter.viewOutput'>log</a>。"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"cap = cv2.VideoCapture(1)\n",
|
|
"cap.open(0)\n",
|
|
"\n",
|
|
"while cap.isOpened():\n",
|
|
" success, frame = cap.read()\n",
|
|
" if not success:\n",
|
|
" print(\"Camera Error\")\n",
|
|
" break\n",
|
|
" \n",
|
|
" frame = process_image(frame)\n",
|
|
" cv2.imshow('Video', frame)\n",
|
|
" \n",
|
|
" if cv2.waitKey(1) & 0xFF == ord('q'):\n",
|
|
" break\n",
|
|
" \n",
|
|
"cap.release()\n",
|
|
"cv2.destroyAllWindows() "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "10fca4bc34a944ea",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "software_engineering",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.8.20"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|