File size: 2,501 Bytes
30230a7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import runpy
import sys
import types
import unittest
from pathlib import Path
from unittest.mock import Mock, patch

import cv2
import numpy as np


class ShowcaseDrawingTests(unittest.TestCase):
    def test_webcam_resolution_changes_preserve_drawing_without_add_error(self):
        # The runner's waiting frame is 640x480; browser webcam frames are 480x360.
        shapes = [(480, 640, 3), (480, 640, 3), (360, 480, 3), (480, 640, 3), (640, 480, 3)]
        camera = Mock()
        camera.read.side_effect = [(True, np.zeros(shape, dtype=np.uint8)) for shape in shapes] + [(False, None)]
        landmarks = [types.SimpleNamespace(x=0.25, y=0.7) for _ in range(21)]
        landmarks[8].y = 0.3
        landmarks[12].y = 0.8
        detector = Mock()
        detector.detect.side_effect = [
            types.SimpleNamespace(hand_landmarks=[landmarks]),
            *[types.SimpleNamespace(hand_landmarks=[]) for _ in shapes[1:]],
        ]
        mp = types.ModuleType("mediapipe")
        tasks = types.ModuleType("mediapipe.tasks")
        python = types.ModuleType("mediapipe.tasks.python")
        vision = types.ModuleType("mediapipe.tasks.python.vision")
        mp.Image = Mock()
        mp.ImageFormat = types.SimpleNamespace(SRGB=1)
        python.BaseOptions = Mock()
        vision.HandLandmarkerOptions = Mock()
        vision.HandLandmarker = types.SimpleNamespace(create_from_options=Mock(return_value=detector))
        mp.tasks, tasks.python, python.vision = tasks, python, vision
        modules = {module.__name__: module for module in (mp, tasks, python, vision)}
        displayed = []
        script = Path(__file__).resolve().parents[1] / "projects/DEMO/展示用學生/03_手指空中畫畫/draw_game_student.py"
        with patch.dict(sys.modules, modules), \
             patch.object(cv2, "VideoCapture", return_value=camera), \
             patch.object(cv2, "imshow", side_effect=lambda title, frame: displayed.append(frame.copy())), \
             patch.object(cv2, "waitKey", return_value=-1), \
             patch.object(cv2, "destroyAllWindows"):
            runpy.run_path(str(script), run_name="__main__")
        self.assertEqual([frame.shape for frame in displayed], shapes)
        self.assertTrue(all(frame.dtype == np.uint8 for frame in displayed))
        self.assertTrue(all(np.any(frame) for frame in displayed), "Existing drawing must survive size changes")
        camera.release.assert_called_once()


if __name__ == "__main__":
    unittest.main()