MediaPipe


MediaPipe เป็นไลบรารีที่พัฒนาโดย Google สำหรับการประมวลผลสื่อ (Media Processing) และมีข้อดีหลายประการเมื่อนำมาใช้ร่วมกับ Python ดังนี้:

  1. การทำงานแบบเรียลไทม์: MediaPipe ถูกออกแบบมาให้สามารถประมวลผลภาพและวิดีโอได้แบบเรียลไทม์ ทำให้สามารถใช้งานได้ในแอปพลิเคชันที่ต้องการความเร็วสูง เช่น การตรวจจับใบหน้าและท่าทาง

  2. ความแม่นยำสูง: MediaPipe ใช้อัลกอริธึมที่มีความแม่นยำสูง เช่น การตรวจจับจุดบนใบหน้า การตรวจจับมือ และการติดตามการเคลื่อนไหวของร่างกาย

  3. การใช้งานง่าย: MediaPipe มีอินเทอร์เฟซที่ใช้งานง่าย สามารถติดตั้งและนำมาใช้งานได้อย่างรวดเร็วผ่าน Python

  4. รองรับหลายแพลตฟอร์ม: MediaPipe สามารถทำงานได้บนหลายแพลตฟอร์ม เช่น Windows, MacOS, Linux, Android และ iOS

  5. ปรับแต่งได้: ผู้ใช้งานสามารถปรับแต่งโมเดลและโฟลว์การประมวลผลให้เหมาะสมกับงานที่ต้องการได้

  6. โอเพ่นซอร์ส: MediaPipe เป็นโอเพ่นซอร์ส ซึ่งหมายความว่าผู้ใช้งานสามารถเข้าถึงซอร์สโค้ดและปรับปรุงไลบรารีได้เองตามต้องการ

  7. มีตัวอย่างและเอกสาร: MediaPipe มีตัวอย่างการใช้งานและเอกสารประกอบที่ครบถ้วน ทำให้ผู้ใช้งานสามารถศึกษาและนำไปใช้งานได้อย่างรวดเร็ว


Firmata

Firmata เป็นโปรโตคอลที่ใช้สำหรับการสื่อสารระหว่างไมโครคอนโทรลเลอร์ เช่น Arduino กับคอมพิวเตอร์หรืออุปกรณ์อื่น ๆ ผ่านทาง Serial (UART) หรือการเชื่อมต่อแบบอื่น ๆ Firmata อนุญาตให้คุณควบคุมและอ่านค่าจากพินของ Arduino ได้จากภายนอก โดยไม่จำเป็นต้องเขียนโค้ดเฉพาะสำหรับ Arduino เอง

ตัวอย่างการใช้งาน Firmata คือการควบคุมพินดิจิตอลและแอนะล็อกของ Arduino จากโปรแกรมบนคอมพิวเตอร์ เช่น Python, Processing หรือ JavaScript ผ่านทาง Serial communication ทำให้การพัฒนาและการทดลองกับ Arduino ง่ายขึ้นมาก

การใช้งาน Firmata กับ Arduino

  1. ติดตั้งไลบรารี Firmata:
    • เปิด Arduino IDE
    • ไปที่เมนู Sketch > Include Library > Manage Libraries...
    • ค้นหา “Firmata” แล้วคลิก Install


  2. อัพโหลดโค้ด 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 โดยใช้ท่าทางมือ


อุปกรณ์ที่ใช้

1- Arduino UNO R3

2- Sensor Shield V 5.0

3- PWM Dimming Adjust 220V Module

4- AC Power Cord 2 Pin Plug

5- แผ่นอะคริลิคใส

6- เสารองแผ่นพีซีบีโลหะแบบเหลี่ยม 8 mm

7- Jumper (F2F) 20cm Female to Female

8- หลอดไฟ 220V + ขั้วหลอดไฟ + สายไฟ


1.ประกอบอุปกรณ์และเชื่อมต่อวงจร

  • ยึด Arduino UNO R3 เข้ากับ เสารองแผ่นพีซีบีโลหะแบบเหลี่ยม 8 mm
This image has an empty alt attribute; its file name is 20240716_103700-1024x768.jpg




  • เสียบ Sensor Shield เข้ากับ บอร์ด Arduino UNO R3

This image has an empty alt attribute; its file name is 20240716_104636-1024x768.jpg




  • เชื่อมต่อ Sensor Shield กับ Dimmer Module


เชื่อมต่อ PWM Dimming Module กับ  อุปกรณ์ไฟฟ้าอื่นๆ

( หลอดไฟควรมีคุณสมบัติหรี่ไฟได้ เช่น หลอดไส้ร้อนแบบธรรมดา 40 – 100 วัตต์ )

This image has an empty alt attribute; its file name is 2-1.jpg
This image has an empty alt attribute; its file name is 1-2-1024x768.jpg

This image has an empty alt attribute; its file name is 2-2-1024x768.jpg





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


ทดสอบการทำงาน



คลิป Arduino ควบคุม การหรี่ไฟ 220V โดยใช้ท่าทางมือ

Leave a Reply

Your email address will not be published. Required fields are marked *

เราใช้คุกกี้เพื่อพัฒนาประสิทธิภาพ และประสบการณ์ที่ดีในการใช้เว็บไซต์ของคุณ คุณสามารถศึกษารายละเอียดได้ที่ นโยบายความเป็นส่วนตัว และสามารถจัดการความเป็นส่วนตัวเองได้ของคุณได้เองโดยคลิกที่ ตั้งค่า

Privacy Preferences

คุณสามารถเลือกการตั้งค่าคุกกี้โดยเปิด/ปิด คุกกี้ในแต่ละประเภทได้ตามความต้องการ ยกเว้น คุกกี้ที่จำเป็น

Allow All
Manage Consent Preferences
  • Always Active

Save