import cv2
import mediapipe as mp
# 미디어파이프 초기화
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
hands = mp_hands.Hands(max_num_hands=1, min_detection_confidence=0.7)
# 버튼 클래스 정의
class Button:
def __init__(self, x, y, w, h, text):
self.rect = (x, y, w, h)
self.text = text
self.hover = False
def draw(self, img):
x, y, w, h = self.rect
color = (0, 255, 0) if self.hover else (255, 0, 0)
cv2.rectangle(img, (x, y), (x + w, y + h), color, -1)
cv2.putText(img, self.text, (x + 20, y + 55),
cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 255, 255), 3)
def is_hover(self, px, py):
x, y, w, h = self.rect
return x <= px <= x + w and y <= py <= y + h
# 웹캠 실행
cap = cv2.VideoCapture(0)
# 버튼 설정값
btn_w, btn_h = 100, 100
gap = 30 # 버튼 간 간격
buttons = []
# 최초 프레임으로 해상도 확인 후 버튼 배치
initialized = False
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
frame = cv2.flip(frame, 1)
h, w, _ = frame.shape
# 버튼 처음 한 번만 계산해서 배치
if not initialized:
start_x = (w - (btn_w * 3 + gap * 2)) // 2
start_y = (h - (btn_h * 3 + gap * 2)) // 2
for row in range(3):
for col in range(3):
num = row * 3 + col + 1
x = start_x + col * (btn_w + gap)
y = start_y + row * (btn_h + gap)
buttons.append(Button(x, y, btn_w, btn_h, str(num)))
initialized = True
# 손 검출
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
result = hands.process(rgb)
index_finger_tip = None
if result.multi_hand_landmarks:
for hand_landmarks in result.multi_hand_landmarks:
mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
# 검지 손가락 끝 (8번 landmark)
index_tip = hand_landmarks.landmark[8]
index_finger_tip = int(index_tip.x * w), int(index_tip.y * h)
# 포인터 표시
cv2.circle(frame, index_finger_tip, 10, (0, 0, 255), -1)
# 버튼 처리
for button in buttons:
button.hover = False
if index_finger_tip and button.is_hover(*index_finger_tip):
button.hover = True
cv2.putText(frame, f"Clicked {button.text}", (50, 50),
cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 0, 255), 2)
print(f"Button {button.text} clicked")
button.draw(frame)
cv2.imshow("Hand Button Click", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 자원 해제
cap.release()
cv2.destroyAllWindows()
hands.close()
<aside> 📌
[과제명][학교][이름] 바꿔주세요, 과제태그를 선생님 설명 듣고 넣어주세요.
</aside>