ルールは次のとおりです: 左手は白いラケットをコントロールし、右手は紫のラケットをコントロールします。ラケットは上下にのみ移動できます。赤い丸はアイスボールです。ボールが上下の青い枠に衝突するとラケットが跳ねます; ボールが黄色のエリアに入るとゲームオーバー; 下のピンクのカウントボードには左右がボールを打った回数が記録されます。
1 2 3 4 5 6 7 8 9 |
|
21 手のキー ポイントの座標は次のとおりです:
始める前に、テーブル、ボール、ラケットの写真を準備します。 PPT を使用して絵を描きました。ボールとラケットの絵は .png 形式で保存する必要があります。読みやすいように同じフォルダーに配置します。
(1) cvzone.HandTrackingModule. HandDetector ()
手のキーポイント検出方法
パラメータ:
mode: デフォルトは False で、入力画像はビデオ ストリームとして扱われます。最初の入力画像で手を検出し、検出に成功した後はさらに手の座標を特定しようとします。後続のイメージでは、すべての maxHands 手が検出され、対応する手の座標が特定されると、いずれかの手の追跡が失われるまで、別の検出を呼び出すことなく、それらの座標を追跡します。これにより遅延が軽減され、ビデオ フレームの処理に最適です。 True に設定すると、無関係である可能性のある静的な画像のバッチを処理するために、各入力画像に対して手の検出が実行されます。
maxHands: 検出する手の最大数、デフォルトは 2
detectionCon: 手検出モデルの最小信頼値 (0 ~ 1)、しきい値を超えた場合、検出は成功しました。デフォルトは 0.5
minTrackingCon: 座標追跡モデルの最小信頼値 (0 ~ 1) で、手の座標を追跡が成功したとみなすために使用されます。失敗した場合は、手の検出が自動的に呼び出されます。次の入力画像です。より高い値に設定すると、ソリューションの堅牢性が向上しますが、待ち時間が長くなります。モードが True の場合、このパラメータは無視され、すべての画像に対して手の検出が実行されます。デフォルトは 0.5
そのパラメータと戻り値は、公式関数 mediapipe.solutions.hands.Hands()
MULTI_HAND_LANDMARKS: 検出/追跡された手のコレクション。それぞれの手がそれぞれ x、y、z で構成される 21 個の手のランドマークのリストとして表されます。
MULTI_HANDEDNESS: 検出/追跡されている手が左か右かのコレクション。各ハンドはラベルとスコアで構成されます。 label は、「Left」または「Right」値を持つ文字列です。スコアは、左手または右手を予測する推定確率です。
(2)cvzone.HandTrackingModule.HandDetector.findHands()
手のキーポイントを見つけて描画
パラメータ:
img: 検出する必要がありますkey Points ポイントのフレーム画像、形式は BGR
draw: 元画像上にキーポイントや認識枠を描画する必要があるかどうか
flipType: 画像を描画する必要があるかどうか反転、ビデオ画像が自分自身の鏡像でない場合は、True に設定してください
戻り値:
hands: 検出された手の情報、0 または 1 または 2 つの辞書で構成されるリスト。 2 つの手が検出された場合、それは 2 つの辞書で構成されるリストになります。辞書には、21 個のキーポイントの座標 (x、y、z)、検出枠の左上の座標とその幅と高さ、検出枠の中心点の座標、およびどの手が検出されたかが含まれます。
img: キーポイントと接続を描画した後に画像を返します
(3)cv2.addWeighted()
画像融合
2 つの画像を混合します画像は特定の比率に従って結合されます。2 つの画像のサイズとチャネル数は同じである必要があります。
2 つの画像は特定の比率に従って結合されます。 cv2.addWeighted(image 1、重み 1、画像 2、重み 2、明るさのバイアス 設定)
は y = a x1 b x2 c に相当します。ここで、a と b は重みを表し、c は明るさをどれだけ明るくするかを表します
#コードのこの部分は、主に手のキー ポイントの検出と、背景画像とビデオ フレーム画像の融合を担当します
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
|
効果図は次のとおりです。 :
##3. キーポイントの処理、ラケットの動き
(1) ラケットをコントロールする
hand['bbox'] 中包含了手部检测框的左上角坐标和检测框的宽高,使用手掌中心点的 y 坐标来控制球拍的上下移动。由于两个球拍的shape是相同的,因此只要获取一个球拍的高度 h2 即可。使用掌心中点 y 坐标控制球拍中点的 y1 坐标,公式为:y1 = (y + h) // 2 - h2 // 2
接着使用 cvzone.overlayPNG() 就可以将球拍图片覆盖在原图片的指定区域,其中坐标参数是指覆盖区域的左上角坐标。固定横坐标,只上下移动。
(2)球移动
首先要规定球的移动速度 speedx, speedy = 10, 10 代表球每一帧沿x轴正方向移动10个像素,沿y轴正方向移动10个像素,那么球的初始合速度方向是沿图片的正右下角移动
如果球碰撞到了球桌的上下边框,就反弹。speedy = -speedy。代表x方向每帧移动的步长不变,y方向每帧移动的方向反转,即入射角等于出射角。
在上述代码中补充
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
|
效果图如下:
这一部分主要完成三项工作,第一是球拍击打到球,球需要反弹;第二是如果球进入黄色区域,游戏结束;第三是左右侧击球得分计数器。
(1)球拍击球
看到代码中的第(5)步,ballpos 代表球的左上角坐标(x,y),100 < ballpos[0] < 100+w1 代表球到了球拍横坐标区域范围内部了,y1 < ballpos[1] < y1+h2 代表球的y坐标在球拍y坐标内部,这时表明击球成功,speedx = -speedx 只改变沿x轴的速度方向,不改变沿y轴的速度方向。
(2)球进黄区,游戏结束
if ballpos[0] < 50 or ballpos[0] > 1150,如果球图片的左上坐标的 x 坐标,在黄区边缘,整个程序退出。当然也可以做一个游戏结束界面,我之前的博文里也有介绍,我偷个懒不写了。
(3)计数器
首先定义个变量初始化记录左右侧的击球次数 score = [0, 0],如果有一侧的球拍击中球,那么对应该侧计数加一。
上面代码是掌心控制球拍,这里改成食指指尖控制球拍中点移动。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
|
效果图如下:
以上がPython を使用してテーブル ホッケーのビジュアル ゲームを作成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。