วันศุกร์ที่ 17 พฤษภาคม พ.ศ. 2562

การปรับปรุงเงื่อนไขของ keymapping

จากเงื่อนไขของการทำ Keymapping ของบทความก่อนหน้านั้น ได้ทดลองปรับปรุงเงื่อนไขใหม่คือ
โดยแบ่งวิธีคิดเป็น 2 วิธีคือ
  1. เก็บค่าในการสั่งงานในแต่ละครั้ง เพื่อใช้ในการเว้นเวลาในการสั่งแต่ละรอบ  
  2. เปลี่ยนการนับจำนวนของการเกิด undefined action ตามเงื่อนไข เป็นการเช็คผลต่างของเวลา
    โดยวิธีแรกนั้นจะตั้งตัวแปรที่จะเปลี่ยนสถานะเมื่อถึงเวลาที่กำหนด (เวลาที่ใช้ในการสั่งงานในแต่ละครั้ง) ใช้สำหรับเช็คเงื่อนไขของการที่จะทำการ mapping ในแต่ละครั้ง โดยในที่นี้จะใช้ตัวแปร start แทน หากเป็น 0 จะทำการไปตรวจเช็คผลต่างของเวลาว่า ครบรอบเวลาการทำงานใน 1 ครั้งหรือไม่ ถ้าหากถึงเวลานั้นแล้วจะเปลี่ยนให้ start เป็น 1
    ต่อมา ถ้าหากเป็น 1 และท่าทางที่เข้ามานั้นไม่ใช่ undefined action จะทำการตรวจสอบท่าทางและทำการ mapping หลังจากนั้นจะทำการ reset timer เพื่อใช้เช็คผลต่างของเวลาในครั้งถัดไป

โดยดูได้จาก state diagram ด้านล่าง



     โดยค่าเวลาที่นำมาใช้เป็นเงื่อนไขนั้น นำมาจากการเก็บเวลาการทำงานในช่วงที่เกิดการนำ gesture ไปเปลี่ยนเป็นคำสั่ง และหาผลต่างของช่วงเวลาที่เกิดขึ้น เพื่อตรวจสอบว่าในการทำงานแต่ละครั้งนั้นมีช่วงเวลาการทำงานที่ห่างกันเป็นเวลาเท่าใด โดยจะเก็บข้อมูลเวลาทั้งหมด 470 ครั้ง มาทำการหาผลต่างและหาค่าเฉลี่ย โดยค่าเฉลี่ยที่ได้นั้นอยู่ที่ 4 วินาที แต่เนื่องจากส่งผลให้เวลาการตอบสนองนั้นช้าเกินไป และเมื่อดูที่ข้อมูล พบว่า ส่วนใหญ่เวลาที่ใช้จะเป็น 1 วินาที ต่อการสั่งงาน 1 ครั้ง จึงลดลงเหลือ 1 วินาที ซึ่งเป็นเวลาที่เกิดขึ้นมากที่สุดในข้อมูล

โดยโค้ดของการทำงานมีดังนี้

def get_gesture():

     fps = 0
     last_gesture = "undefined action"
     t0 = time.time()

     start_time = timer()
     start = 1 # use as a state check

     while True:
          # get depth input and do image processing and blob tracking
          input.get_input()
          # get gesture from input data
          gesture = input.check_gesture(fps)
          t1 = time.time()
          fps = 1/(t1-t0)
          print("Gesture : %s" %gesture)

          # if state is ready and new gesture is not undefined
          if start == 1 and gesture != "undefined action":
               # set state check to not ready
               start = 0
               if last_gesture != gesture:
                    key_mapping(gesture)
               last_gesture = gesture

               end_time = timer()
               diff_time = end_time - start_time
               print("Action time : %s \n" %diff_time)
               start_time = end_time

          else:

               end_time = timer()
               diff_time = end_time - start_time
               print("Different time : %s \n" %diff_time)
               if diff_time >= 1:
                    start = 1
                    start_time = end_time

               last_gesture = "undefined action"

          t0 = t1

วิธีที่ 2 จะแบ่งเป็น 2 เงื่อนไข ดังนี้

  1. หาก gesture ล่าสุดต่างกับ previous gesture จะทำการตรวจสอบก่อนว่า previous gesture นั้นเป็น undefined action หรือไม่ หากใช่ แสดงว่าอาจเกิดช่วงของข้อมูลที่ตกหล่นไป จะทำการเช็คอีกเงื่อนไขคือ gesture ก่อนเกิด undefined action นั้นต่างกับ gesture ล่าสุดหรือไม่ หากไม่ต่างกันแสดงว่าเกิดการตกหล่นของข้อมูลจริง จะไม่สั่งการเพิ่ม หากผลออกมาต่างกัน จะทำการ mapping คำสั่งตาม gesture ใหม่ที่เข้ามา 
  2. หาก gesture ที่เข้ามาเป็น undefined action จะทำการเช็คเวลาว่าเป็น ช่วงของ undefined action หรือไม่ หากใช่จะทำการปรับค่า gesture ที่บันทึกไว้สำหรับเช็คช่วงของข้อมูลที่ตกหล่นให้เป็น undefined action เพื่อป้องกันกรณีที่ต้องการสั่งคำสั่งเดิมอีกครั้งแต่ระบบมองว่าเป็นคำสั่งเดิมที่เกิดจากข้อมูลตกหล่นอันเป็นผลมาจากเงื่อนไขที่ 1
เมื่อทำเสร็จเงื่อนไขใดเงื่อนไขหนึ่ง จะทำการ reset timer เพื่อนำไปใช้ในการคำนวณเงื่อนไขเวลาในครั้งถัดไป โดยสามารถดูเพิ่มเติมได้จาก state diagram ดังรูปด้านล่าง



โดยค่าเวลานี้ได้มาจากการจับเวลาช่วงที่เกิด undefined action ใน 1 ครั้ง ว่าในตอนที่ตรวจจับไม่พบหรือไม่มีท่าทางเข้ามานั้นจะใช้เวลาในการตรวจจับเท่าใด โดยทำการเก็บเวลาที่ใช้ในการเกิด undefined action มาทั้งหมด160 ครั้ง และนำมาหาค่าเฉลี่ยซึ่งได้เวลาเฉลี่ยต่อการการเกิด undefined action อยู่ที่ 0.04 วินาที และต้องการเว้นช่วงที่ใช้ในการตรวจสอบประมาณ 7 ช่วง จึงได้เวลาที่ใช้สำหรับเงื่อนไขเป็น 0.04*7 เท่ากับ 0.28 วินาทีโดยประมาณ

โดยโค้ดของการทำงานวิธีที่2มีดังนี้

def get_gesture():

     fps = 0
     last_gesture = "undefined action"
     t0 = time.time()

     start_time = timer()
     # use to count undefined action
     undefined_count = 0
     # use to save state of gesture to check
     state_gesture = ""

     while True:

          input.get_input() # get depth input and do image processing and blob tracking
          gesture = input.check_gesture(fps) # get gesture from input data
          t1 = time.time()
          fps = 1/(t1-t0)
          print("Gesture : %s \n" %gesture)

          if gesture == "undefined action":

               end_time = timer()
               diff_time = end_time - start_time
               print("Different time : %s" %diff_time)

               if diff_time >= 0.28:
                    state_gesture = "undefined action"
                    start_time = end_time
                    last_gesture = "undefined action"

          # if latest gesture is not same as last gesture
          elif last_gesture != gesture:

               # if last gesture is undefined
               if last_gesture == "undefined action":
                    # check previous state before undefined if same as latest not
                    if state_gesture != gesture:
                         # if not map gesture
                         key_mapping(gesture)

               else:
                    # if last gesture is other gesture then map gesture
                    key_mapping(gesture)

               # set last gesture with latest gesture
               last_gesture = gesture
               # set state with latest gesture
               state_gesture = gesture
               # reset count
               undefined_count = 0

               end_time = timer()
               diff_time = end_time - start_time
               print("Action time : %s" %diff_time)
               start_time = end_time

          t0 = t1

     จากการทดสอบทั้ง 2 รูปแบบของเงื่อนไขนั้นพบว่าสามารถใช้งานได้ใกล้เคียงกัน และเวลาต่ำสุดที่สามารถตั้งเป็นเงื่อนไขโดยเกิดการสั่งเกินน้อยที่สุดอยู่ที่ 0.8 วินาที แต่จะพบว่ามีการหน่วงในการสั่งการเล็กน้อยเมื่อเทียบกับแบบที่ทำการ fixed parameter จากบทความก่อนหน้า

ไม่มีความคิดเห็น:

แสดงความคิดเห็น