MediaPipe
MediaPipe เป็นไลบรารีที่พัฒนาโดย Google สำหรับการประมวลผลสื่อ (Media Processing) และมีข้อดีหลายประการเมื่อนำมาใช้ร่วมกับ Python ดังนี้:
- การทำงานแบบเรียลไทม์: MediaPipe ถูกออกแบบมาให้สามารถประมวลผลภาพและวิดีโอได้แบบเรียลไทม์ ทำให้สามารถใช้งานได้ในแอปพลิเคชันที่ต้องการความเร็วสูง เช่น การตรวจจับใบหน้าและท่าทาง
- ความแม่นยำสูง: MediaPipe ใช้อัลกอริธึมที่มีความแม่นยำสูง เช่น การตรวจจับจุดบนใบหน้า การตรวจจับมือ และการติดตามการเคลื่อนไหวของร่างกาย
- การใช้งานง่าย: MediaPipe มีอินเทอร์เฟซที่ใช้งานง่าย สามารถติดตั้งและนำมาใช้งานได้อย่างรวดเร็วผ่าน Python
- รองรับหลายแพลตฟอร์ม: MediaPipe สามารถทำงานได้บนหลายแพลตฟอร์ม เช่น Windows, MacOS, Linux, Android และ iOS
- ปรับแต่งได้: ผู้ใช้งานสามารถปรับแต่งโมเดลและโฟลว์การประมวลผลให้เหมาะสมกับงานที่ต้องการได้
- โอเพ่นซอร์ส: MediaPipe เป็นโอเพ่นซอร์ส ซึ่งหมายความว่าผู้ใช้งานสามารถเข้าถึงซอร์สโค้ดและปรับปรุงไลบรารีได้เองตามต้องการ
- มีตัวอย่างและเอกสาร: MediaPipe มีตัวอย่างการใช้งานและเอกสารประกอบที่ครบถ้วน ทำให้ผู้ใช้งานสามารถศึกษาและนำไปใช้งานได้อย่างรวดเร็ว
Firmata
Firmata เป็นโปรโตคอลที่ใช้สำหรับการสื่อสารระหว่างไมโครคอนโทรลเลอร์ เช่น Arduino กับคอมพิวเตอร์หรืออุปกรณ์อื่น ๆ ผ่านทาง Serial (UART) หรือการเชื่อมต่อแบบอื่น ๆ Firmata อนุญาตให้คุณควบคุมและอ่านค่าจากพินของ Arduino ได้จากภายนอก โดยไม่จำเป็นต้องเขียนโค้ดเฉพาะสำหรับ Arduino เอง
ตัวอย่างการใช้งาน Firmata คือการควบคุมพินดิจิตอลและแอนะล็อกของ Arduino จากโปรแกรมบนคอมพิวเตอร์ เช่น Python, Processing หรือ JavaScript ผ่านทาง Serial communication ทำให้การพัฒนาและการทดลองกับ Arduino ง่ายขึ้นมาก
การใช้งาน Firmata กับ Arduino
- ติดตั้งไลบรารี Firmata:
- เปิด Arduino IDE
- ไปที่เมนู
Sketch
>Include Library
>Manage Libraries...
- ค้นหา “Firmata” แล้วคลิก
Install
- อัพโหลดโค้ด Firmata ไปยัง Arduino:
- เปิด
File
>Examples
>Firmata
>StandardFirmata
- เปิด
- อัพโหลดโค้ดนี้ไปยังบอร์ด Arduino ของคุณ
*** การทำงานที่คอมพิวเตอร์ ***
1. ติดตั้ง Python 3.10.0
2. ติดตั้งโปรแกรม PyCharm
เลือกติดตั้งตัวฟรี คือ PyCharm Community
3. เพิ่มแพคเก็จ pyFirmata
เปิดโปรแกรม PyCharm Community เลือก New Project ตั้งชื่อชื่อโปรเจคตามตัวอย่างคือ FirmataProject -> Create
สร้างไฟล์ใหม่
ในตัวอย่างชื่อ test.py
สำหรับ Python, คุณสามารถใช้ไลบรารี pyFirmata
เพื่อสื่อสารกับบอร์ด Arduino
ตัวอย่างโค้ด Python:
from pyfirmata import Arduino, util
import time
board = Arduino('COM3') # หรือพอร์ตที่ Arduino ของคุณเชื่อมต่อ
it = util.Iterator(board)
it.start()
pin = board.get_pin('d:13:o') # ใช้พินดิจิตอล 13 เป็น output
while True:
pin.write(1) # เปิด LED
time.sleep(1)
pin.write(0) # ปิด LED
time.sleep(1)
เพิ่มแพคเก็จ Firmata โดยไปที่ File -> Settings…
ไปที่ Python Interpreter เลือก แล้ว คลิกเครื่องหมาย +
ที่ช่องค้นหา พิมพ์ pyfirmata -> คลิกที่ pyFirmata-> Install Package
จะพบแพคเก็จ pyFirmata และ pyserial เพิ่มเข้ามา -> OK
เชื่อมต่อสาย USB จาก คอมพิวเตอร์ ไปที่บอร์ด Arduino UNO ที่อัพโหลดโค้ด Firmata เรียบร้อยแล้ว
ทดสอบ Run
ไม่พบ Error ใดๆ
หลอดไฟ LED กระพริบติด-ดับ แสดงว่า พร้อมที่จะทำงานในขั้นตอนต่อไปแล้ว
4. ติดตั้งแพคเก็จ numpy , opencv-python , mediapipe , controller , cvzone , pynput
ติดตั้งแพคเก็จ numpy
NumPy เป็นแพ็คเกจ (package) ในภาษา Python ที่ถูกพัฒนาขึ้นมาเพื่อการคำนวณเชิงตัวเลขและวิทยาศาสตร์ข้อมูล ซึ่งมีความสามารถหลากหลายในการจัดการกับอาเรย์ (arrays) และเมทริกซ์ (matrices) รวมถึงฟังก์ชันทางคณิตศาสตร์ที่สามารถใช้กับอาเรย์ได้อย่างมีประสิทธิภาพ
ติดตั้งแพคเก็จ opencv-python
opencv-python เป็นแพ็คเกจในภาษา Python ที่ใช้สำหรับการประมวลผลภาพและวิดีโอ เป็นเวอร์ชันของ OpenCV (Open Source Computer Vision Library) ซึ่งเป็นไลบรารีโอเพนซอร์สที่มีฟังก์ชันมากมายสำหรับการวิเคราะห์ภาพและวิดีโอ
ติดตั้งแพคเก็จ mediapipe
MediaPipe เป็นแพ็คเกจใน Python ที่พัฒนาโดย Google ซึ่งใช้สำหรับการประมวลผลข้อมูลมัลติโมดัล (multimodal data) โดยเฉพาะการวิเคราะห์ข้อมูลจากภาพ, วิดีโอ, และเสียง โดยแพ็คเกจนี้เน้นไปที่การใช้งานในงานปัญญาประดิษฐ์ (AI) และการเรียนรู้ของเครื่อง (Machine Learning) เพื่อตรวจจับและติดตามวัตถุหรือจุดสนใจในสื่อมัลติมีเดียต่าง ๆ
ติดตั้งแพคเก็จ controller
เป็นเครื่องมือที่ช่วยให้จับเหตุการณ์ UI ทุกประเภทได้ เช่น การแตะหน้าจอโทรศัพท์เคลื่อนที่หรือการเร่งความเร็วของอุปกรณ์โดยตรงในโค้ด Python
ติดตั้งแพคเก็จ cvzone
cvzone เป็นไลบรารี Python ที่สร้างขึ้นเพื่อทำให้การใช้งาน OpenCV (Open Source Computer Vision Library) และ MediaPipe ง่ายขึ้น โดย cvzone เป็นการรวมเครื่องมือและฟังก์ชันที่ใช้บ่อยในงานประมวลผลภาพและวิดีโอ รวมถึงการประมวลผลคอมพิวเตอร์วิทัศน์ (computer vision) และการเรียนรู้ของเครื่อง (machine learning) เข้าไว้ด้วยกันในรูปแบบที่ง่ายและสะดวกต่อการใช้งาน
ติดตั้งแพคเก็จ pynput
pynput เป็นแพ็คเกจ Python ที่ใช้สำหรับการควบคุมและตรวจจับการอินพุตจากอุปกรณ์อินพุตของผู้ใช้ เช่น คีย์บอร์ดและเมาส์ โดยคุณสามารถใช้ pynput ในการสร้างสคริปต์เพื่อจัดการการกระทำต่าง ๆ ที่เกิดจากการกดปุ่มคีย์บอร์ดหรือการเคลื่อนที่และคลิกของเมาส์ ซึ่งเหมาะสำหรับงานที่ต้องการควบคุมอุปกรณ์เหล่านี้หรือฟังก์ชันที่ตอบสนองต่อการกระทำของผู้ใช้
การสร้าง โปรเจค Arduino ควบคุม การหรี่ไฟ 220V โดยใช้ท่าทางมือ
อุปกรณ์ที่ใช้
3- PWM Dimming Adjust 220V Module
6- เสารองแผ่นพีซีบีโลหะแบบเหลี่ยม 8 mm
7- Jumper (F2F) 20cm Female to Female
8- หลอดไฟ 220V + ขั้วหลอดไฟ + สายไฟ
1.ประกอบอุปกรณ์และเชื่อมต่อวงจร
- ยึด Arduino UNO R3 เข้ากับ เสารองแผ่นพีซีบีโลหะแบบเหลี่ยม 8 mm
- เสียบ Sensor Shield เข้ากับ บอร์ด Arduino UNO R3
- เชื่อมต่อ Sensor Shield กับ Dimmer Module
เชื่อมต่อ PWM Dimming Module กับ อุปกรณ์ไฟฟ้าอื่นๆ
( หลอดไฟควรมีคุณสมบัติหรี่ไฟได้ เช่น หลอดไส้ร้อนแบบธรรมดา 40 – 100 วัตต์ )
2. อัพโหลดโค้ดและทดสอบ
เปิดโปรแกรม Arduino IDE เขียนโค้ดและอัพโหลดโค้ดดังนี้
int PWM_Pin = 9;
void setup() {
pinMode(PWM_Pin, OUTPUT);
}
void loop() {
analogWrite(PWM_Pin, 0);
delay(1000);
analogWrite(PWM_Pin, 64);
delay(1000);
analogWrite(PWM_Pin, 127);
delay(1000);
analogWrite(PWM_Pin, 191);
delay(1000);
analogWrite(PWM_Pin, 255);
delay(1000);
}
ผลลัพธ์การทำงาน :
- หลอดไฟสว่าง 0 %
- หลอดไฟสว่าง 25 %
- หลอดไฟสว่าง 50 %
- หลอดไฟสว่าง 75 %
- หลอดไฟสว่าง 100 %
คลิปทดสอบ Arduino หรี่ไฟบ้าน
แสดงว่า การเชื่อมต่อ PWM Dimming Module ของเรานั้นถูกต้อง และ พร้อมใช้งานแล้ว
3 : อัพโหลดโค้ด เพื่อรอคำสั่งจาก Python
อัพโหลดโค้ด Firmata ไปยัง Arduino:
เปิด File > Examples > Firmata > SimpleAnalogFirmata
ที่คอมพิวเตอร์เขียนโค้ดดังนี้
import cv2
import mediapipe as mp
import math
import pyfirmata
import numpy as np
# mediapipe library requires us to provide a "confidence" value that determines how strictly it must check for hands.
# here we are informing pyfirmata which port to use
my_port = 'COM3'
board = pyfirmata.Arduino(my_port)
iter8 = pyfirmata.util.Iterator(board)
iter8.start()
# pin number of our servo motor is 9
pin9 = board.get_pin('d:9:s')
# the following three lines are to help us change the colors of our finger tips and line joining them in mediapipe library
mp_drawing = mp.solutions.drawing_utils
hand_mpDraw = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands
# the motor function will send the isntruction to our pyfirmata library which will send it to our arduino
def move_servo(angle):
pin9.write(angle)
# Since we cannot create a dotted line in openCV directly, I wrote a function that will take two points and create a dotted line betweenn them.
# we are using this dotted line to adjust the intensity of light
def drawline(img, pt1, pt2, color, thickness=1, style='dotted', gap=20):
dist = ((pt1[0] - pt2[0]) ** 2 + (pt1[1] - pt2[1]) ** 2) ** .5
pts = []
for i in np.arange(0, dist, gap):
r = i / dist
x = int((pt1[0] * (1 - r) + pt2[0] * r) + .5)
y = int((pt1[1] * (1 - r) + pt2[1] * r) + .5)
p = (x, y)
pts.append(p)
if style == 'dotted':
for p in pts:
cv2.circle(img, p, thickness, color, -1)
else:
s = pts[0]
e = pts[0]
i = 0
for p in pts:
s = e
e = p
if i % 2 == 1:
cv2.line(img, s, e, color, thickness)
i += 1
cap = cv2.VideoCapture(0)
# distance is a variable that we will use later in our code. But we must initiate it beffore our while loop. so iam providing it with a garbage value
distance = -19723086135
with mp_hands.Hands(
min_detection_confidence=0.5,
min_tracking_confidence=0.5) as hands:
while cap.isOpened():
success, image = cap.read()
image = cv2.flip(image, 1)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image.flags.writeable = False
results = hands.process(image)
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
exit_x, exit_y = 700, 100
exit_w, exit_h = 400, 100
# The next line is used to create a rectangle with x,y and w,h cordinates
cv2.rectangle(image, (exit_x, exit_y), (exit_x + exit_w, exit_y + exit_h), (255, 0, 255), cv2.FILLED)
# The next line will put some text on our image
cv2.putText(image, "Join your index and middle fingers to exit", (exit_x + 30, exit_y + 65),cv2.FONT_HERSHEY_PLAIN, 2, (255, 255, 255), 2)
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
lmList = []
for id, lm in enumerate(hand_landmarks.landmark):
h, w, c = image.shape
cx, cy = int(lm.x * w), int(lm.y * h)
lmList.append([id, cx, cy])
tips = [0, 4, 8, 12, 16, 20]
if id in tips:
cv2.circle(image, (cx, cy), 15, (255, 255, 255), cv2.FILLED)
drawline(image, (lmList[4][1], lmList[4][2]), (lmList[8][1], lmList[8][2]), (255, 255, 255),thickness=1, style='dotted', gap=10)
# let us calculate the distance between them and assign it to a variable named "angle"
angle = int(math.hypot(lmList[8][1] - lmList[4][1], lmList[8][2] - lmList[4][2]) / 1.4)
print(angle)
# let's call our "move_servo" function.
move_servo(angle)
mp_drawing.draw_landmarks(image,hand_landmarks,mp_hands.HAND_CONNECTIONS,landmark_drawing_spec=hand_mpDraw.DrawingSpec(color=(0, 0, 0)),connection_drawing_spec=hand_mpDraw.DrawingSpec(color=(201, 194, 2)))
cv2.imshow('MediaPipe Hands', image)
cv2.waitKey(1)
cap.release()
cv2.destroyAllWindows()
https://lungmaker.com/code/dimmer-firmata.py
ทดสอบการทำงาน