VirtualArm Sort & Store [Computer vision]

Intro

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

รับผิดชอบโดย => นายกวิน แย้มต่วน 66340700401

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

Objective

  • สามารถจำแนก class ของวัตถุได้
  • สามารถบอกพิกัดของวัตถุได้ (x,z)

Material and Method

เริ่มต้นด้วยการแสดงภาพรวมของระบบประมวลผลด้วย flow chart เริ่มต้นการทำงานคือทำการเปิดกล้องโดยในตัวโปรแกรมมันจะมีการตรวจสอบสถานะก่อนการเริ่มทำงาน ถ้าหากไม่สามารถเชื่อมต่อกับกล้องได้ระบบจะตัดการทำงานทันทีต้องรันโปรแกรมใหม่ จากนั้นถ้าหากกล้องพร้อมใช้งานและโปรแกรมสามารถเข้าถึงข้อมูลภาพจากล้องได้จะทำการเก็บข้อมูลภาพไว้จากนั้นจะเข้าสู่สภานะเริ่มการทำงานโดยผู้ใช้ต้องเป็นคนระบุบริเวณพื้นที่การทำงาน จะนั้นจะเป็นเป็นตัวแปลไว้ใช้ในการเช็คพื้นที่การทำงาน เพราะด้วยความที่บริเวณที่กล้องเห็นทั้งหมดมีพื้นที่อื่นๆด้วยทำให้อาจจะมีความผิดพลาดในการระบุวัตถัได้ จากนั้นจะนำภาพที่อ่านเข้าสู่โปรแกรมหลักคือระบบประมวลผลที่ใช้ในการระบุวัตถุด้วยสี ถ้าหากเจอสีไหนก็จะเก็บเป็นข้อมูลไว้ถ้าหากมีสีนั้นเกินกว่า 1 ชิ้นมันจะทำการเก็บข้อมูล ID ไว้ด้วยคือ 0 1 2 เป็นต้น นี้คือการทำงานทั้งหมด ในส่วนของระบบประมวลผลหลักจะอธิบายในส่วนต่อไป

ภาพรวมของงานจะแสดงในวิดีโอ ในงานนี้จะเป็นการตรวจจับวัตถุที่มีสีของฝาที่แตกต่างกันโดยเครื่องมือที่ใช้หลักๆจะเป็น openCV จะถูกเขียนด้วยภาษา Python โปรแกรมนี้จะสามารถตรวจจับตำแหน่งของวัตถุแต่ละสี ซึ่งสามารถระบุตำแหน่ง และสีของมันได้ วิดีโอแรกจะเป็นการเปรียบเทียบ pixel กับระยะจริง จะแสดงประสิทธิภาพในการเปรียบเทียบนี้ในส่วนสุดท้าย วิดีโอที่ 2 จะแสดงกระบวนการทั้งหมดของการใช้โปรแกรมนี้

ในงานนี้ได้ใช้กล้องที่มีชื่อว่า ZED mini stereo camera ซึ่งกล้องนี้มีวิธีการดึงภาพที่แตกต่างจากการใช้กล้อง webcam ทั่ว

# ซึ่งข้อมูลภาพจะถูกอ่านด้วย 
zed.retrieve_image(image_left, sl.VIEW.LEFT)
zed.retrieve_image(image_right, sl.VIEW.RIGHT)
# ข้อมูลภาพจะถูกนำไปเก็บไว้
img = image_left.get_data()

ระบบประมวลผลหลักของระบบวิเคราะห์ภาพ

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

โดยโปรแกรมจะมีการตั้งช่วงของสีแดงไว้ และภาพที่นำเข้ามาในตอนแรกจะถูกแปลงเป็นปริภูมิสี HSV ก่อน

low_red1 = np.array([170, 70, 50]) # ช่วงของสีแดงในปริภูมิสี HSV
high_red1 = np.array([180, 255, 255]) 
red_mask1 = cv2.inRange(hsv_frame, low_red1, high_red1) # ตัดส่วนของรูปภาพที่มีสีตามช่วงที่กำหนด
low_red2 = np.array([0, 70, 50]) # = ช่วงของสีแดงในปริภูมิสี HSV
high_red2 = np.array([10, 255, 255])
red_mask2 = cv2.inRange(hsv_frame, low_red2, high_red2)
red_mask = red_mask1 | red_mask2 # จากนั้นจะนำผลของการตัดภาพจากช่วงที่กำหนดไว้ทั้งสองอันไว้ที่ mask เพื่อนำไปใช้ในการระบุวัตถุในภาพจริง

ช่วงของสีน้ำเงินจะอยู่ที่

low_blue = np.array([94, 80, 2])
high_blue = np.array([126, 255, 255])
blue_mask = cv2.inRange(hsv_frame, low_blue, high_blue)

ช่วงของสีเขียวจะอยู่ที่

low_green1 = np.array([25, 52, 72])
high_green1 = np.array([102, 255, 255])
green_mask1 = cv2.inRange(hsv_frame, low_green1, high_green1)

จากนั้นภาพที่ถูกแยกโดยใช้ช่วงสีดังกล่าวแล้วจะผลลัพธ์ออกมาเป็นส่วนที่น่าจะเป็นสีนั้น จากนั้นจะมีการประยุกต์ cv2.findContours เพื่อใช้ในการหาพื้นที่ของภาพรวมทั้งตำแหน่งกึ่งกลางจากนั้นจะใช้พื้นที่นั้นในการเช็คเงื่อนไขว่าถ้าหากพื้นที่บริเวณนั้นมีขนาดมากกว่า area_min ก็จะนับว่าพื้นที่นั้นเป็นวัตถุ จากนั้นก็จะเก็บข้อมูลในแต่ละรอบและใส่ไว้ใน return img, red, blue, green โดยที่ img จะเป็นภาพที่เป็นผลลัพธ์

 red = [n_red, c_red, red_mask]
 blue = [n_blue, c_blue, blue_mask]
 green = [n_green, c_green, green_mask]

โดยที่ n คือ จำนวนของวัตถุที่เป็นสีนั้น c คือตำแหน่งกึ่งกลางของวัตถุพร้อมทั้ง id ของมัน mask คือพื้นที่ของวัตถุที่ถูกแยกออกจากพื้นหลังแล้ว

ในส่วนของการสื่อสารระหว่างโปรแกรม

ในงานนี้จะใช้การสื่อสารผ่าน MQTT โดยใน code จะมีการเขียนแยกไว้ระหว่างการ Pub และการ Sub โดยต้องระบุ topic ที่ต้องการ และ broker_address

ลำดับการทำงาน

state ที่ t = 0 ก็คือเมื่อเริ่มต้น หุ่นจะต้องเคลื่อนที่ไปยังตำแหน่งการส่องวัตถุ เมื่อหุ่นเคลื่อนที่ไปถึงตำแหน่งนั้นระบบควบคุมจะส่งข้อความมาด้วยคำว่า ‘set_camera’ มาให้กับระบบ vision ซึ่งระบบ vision ก็จะทำการอ่านภาพเพื่อนำไปใช้ในการประมวลผล

จากนั้นเมื่อมีการทำงานเป็นครั้งแรกระบบประมวลผลจะทำให้ให้ผู้ใช้เลือกพื้นที่การทำงาน ในรอบอื่นๆจะไม่มีขั้นตอนนี้ยกเว้นเป็นคุณรันโปรแกรมใหม่

ก็จะประกอบไปด้วยเริ่มจากการรับข้อมูลจากกล้อง จากนั้นระบบจะให้ผู้ใช้เลือกว่าต้องการใช้พื้นที่บริเวณไหนเป็นพื้นที่การทำงานบ้าง จากนั้นเมื่อผู้ใช้เลือกเสร็จระบบจะเปลี่ยน state r เป็นการดำเนินการถัดไป

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

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

state = 0 เป็นตอนเริ่มต้นเพื่อรอหุ่นเคลื่อนที่ไปยังตำแหน่งของการตั้งกล้อง

เมื่อมาถึงส่วนของโปรแกรมหลักจะมีการเช็คว่าตอนนี้ในพื้นที่การทำงานมีวัตถุสีอะไรอยู่บ้าง แล้วจะเก็บสถานะของแต่ละสีไว้ใน check จากนั้นจะทำการส่งข้อมูลไปให้กับระบบ VR ด้วย topic UR/vision/object โดยจะส่งเป็น 1,1,0 สภานะ 1 คือมีวัตถุสีนั้นอยู่ 0 คือไม่มีอยู่โดยเรียงเป็น RGB

ต่อมาจะเป็นส่วนของการรอรับคำสั่งจากผู้ใช้ว่าผู้ใช้จะเลือกหยิบวัตถุสีไหน โดยถ้าผู้ใช้เลือกแล้ว VR จะส่งข้อมูลมาให้ด้วย topic UR/unity/bottle โดยจะส่ง blue/green/red มา

เมื่อได้รับข้อมูลแล้วระบบ vision ก็จะทำการส่งข้อมูลไปยังระบบควบคุมโดยผ่าน topic UR/vision/position จะส่งข้อมูลเป็นพิกัด x,z ไปเป็นพิกัดที่มีการปรับการเทียบเรรียบร้อยแล้ว นี้ก็จะเป็นทั้งหมดของโปรแกรม โปรแกรมก็จะรอคำสั่งจากระบบควบคุมว่า set_camera แล้วก็จะอ่านภาพใหม่และผ่านกระบวนการเดิมวนไป

source code

https://github.com/KawinYamtuan/Foundation_vision-2024.git

function สำหรับการคำนวณ Rotation matrix

function นี้จะใช้ในการเทียบ frame ของกล้องกับ frame ของปลายหุ่นเพื่อให้ได้ตำแหน่งของวัตถุเมื่อเทียบกับ frame ของหุ่น

Gantt Chart: Project Planner

ผลการทดสอบความแม่นยำของการระบุตำแหน่งของระบบประมวลผล

จะเห็นจากผลการทดลองว่าความคาดเคลื่อนของตำแหน่งมีไม่ถึง 10 % ซึ่งเป็นที่พอรับได้เพราะด้วยจุดประสงค์ของระบบนี้ต้องการให้คนมี่วนร่วมได้ดังนั้นตำแหน่งที่ไม่ได้แม่นยำในระดับหน่วย mm ก็พอที่จะใช้งานได้ วิธีการแก้ไขอาจจะเป็นการทำให้ระบบประมวลผลมีการปรับ parameter ของกล้องบางอย่างหรือการทำเทคนิค image processing เเพิ่มเติมเพื่อให้ความสามารถในการประมวลผลภาพมีประสิทธิภาพมากยิ่งขึ้น

สมการที่ใช้ในการคำนวณค่าความคาดเคลื่อน

ขั้นตอนในการวัดผล

  • วางเส้นแนวเเกนตามแนวแกน X Z ของหุ่นยนต์
  • ใช้ระบบประมวลในการระบุตำแหน่งของวัตถุ จากนั้นใช้อุปกรณ์วัดในการวัดตำแหน่งที่ได้จริงๆ
  • บันทึกผลลง excel จากนั้นทำการวิเคราะห์ผล
  • ตำแหน่งในตารางจะเรียงตามเข็มนาฬิกา 1 – 4
วิดีโอนี้จะแสดงการทำงานร่วมกันทั้งระบบ แต่จะสังเกตึเห็นข้อจำกัดของระบบประมวลผลคือยังไม่มีการเขียนในส่วนของ multi threading ที่จะให้ภาพสามารถแสดงได้อย่าง real time แต่ในตอนนี้โปรแกรมจะแสดงแค่ตอนต้องรับภาพเพื่อประมวลผลเท่านั้น อาจจะเป็นงานในอนาคต

conclusion

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