OpenCV and Python Color Detection

ผู้เขียนบทความ : นาย เอกกวี จิตจำ

1.ความเป็นมา

Color detection เป็นหนึ่งในวิธีการทำ Partial Segmentation อ่านเพิ่มเติมได้ที่ ทำความรู้จักกับ Image Segmentation ซึ่งถ้าแปลตรงๆ ก็คือ การตรวจจับสี (ที่เราสนใจในภาพ) โดยภาพปกติทั่วไปจะใช้รูปแบบของสีเป็น RGB นั้นหมายความว่าภาพที่เห็นประกอบขึ้นจากการรวมกันของภาพ 3 ภาพ โดยแต่ละภาพจะเก็บค่า Intensity สีแดง สีเขียว และสีน้ำเงิน ไว้ตามลำดับ

ในทาง image processing โหมดสีต่างๆ เราจะเรียกเป็น color model ซึ่งไม่ได้มีแค่ RGB เท่านั้น แต่ยังมี model อื่นๆอีก เช่น HSV, Lab, และ HSL เป็นต้น

ตอนนี้เราก็รู้จัก color model กันคร่าวๆละ เราจะย้อนกลับไปที่ภาพ RGB ปกติก่อน แล้วลองจินตนาการดูว่าในแต่ละ Pixel ในภาพมันควร ประกอบไปด้วยค่าทั้งหมดกี่ค่า

2.วัตถุประสงค์

ในการอธิบายจะใช้ rgb model นะครับ แต่จริงๆแล้ว OpenCV จะใช้ model สีเป็น BGR นะครับไม่ใช่ RGB

คำตอบ คือ 3 ค่า เหมือนกับเรามีสีแดง(R) สีเขียว(G) และสีน้ำเงิน(B) แล้วก็ผสมทั้ง 3 สีเข้าด้วยกันในปริมาณที่ต่างกัน เพื่อให้ได้ Pixel ที่มีสีที่เราต้องการ เช่น อยากได้สีแดง ค่าที่ได้ก็จะเป็น (255, 0, 0) เป็นต้น

ตอนนี้ถ้าเราอยาก detect ส่วนสีแดงของรถ sport คันขวา เราจะหาค่าของสีแดงทุก Pixel ยังไงดีละ ถ้าจะนั่งผสมสี แล้วก็ปรับค่า rgb ไปเรื่อยๆก็คงไม่ work เพราะ จากรูปข้างบนจะเห็นว่าค่า r ลดเหลือ 83 ค่า g กับ b เท่ากับ 1 เราจะหาค่าสีเป๊ะๆ ของทุก pixel ได้ไงใช่มั้ยครับ

        -ทำให้โลกนี้เกิด color model ที่ชื่อว่า HSV ขึ้นมา (อันนี้เว่อไปๆ แต่มันก็ดีจริง) โดยแบ่งเป็น 3 ค่าเหมือนกันค่าของแต่ละ channel ยึดตาม OpenCV นะครับ คราวนี้ถ้าเราอยากได้สีแดงตรงรถ sport ก็แค่กำหนด H เป็น 160 – 180 แล้วก็ปรับค่า S กับ V เอาจะเห็นว่าง่ายกว่าเยอะเลย เพราะ สีถูกกำหนดโดย Hue ตัวเดียว

        -ทีนี้เราลองมาเขียนโค้ดกันดีกว่าครับ โดย OpenCV จะมี function cv2.inRange(image, lower, upper) สำหรับการตรวจหา Pixel ที่มีค่าสีอยู่ในช่วงที่เรากำหนด

โดย lower และ upper จะเก็บอยู่ในรูปแบบ numpy array เดี๋ยวจะยกตัวอย่างให้ดูนะครับ

และ return ผลลัพธ์เป็น binary image หรือเรียกอีกอย่างว่า mask โดยสีขาว คือ pixel ที่มีค่าสีอยู่ในช่วงที่เรากำหนด ส่วน pixel อื่นๆจะเป็นสีดำหมดเลย

3.ขอบเขต

ตอนนี้เรามีค่าต่ำสุดและสูงสุดของสีความอิ่มตัวและค่าแล้วเราจะใช้ค่านี้เพื่อกรองภาพออกเพื่อให้เราได้เอาต์พุตสีเฉพาะของภาพ

เราจะสร้างมาสก์สำหรับสิ่งนี้โดยใช้ฟังก์ชัน cv2.inRange และก่อนหน้านั้นเราจะกำหนดขีด จำกัด บนและล่างของสีความอิ่มตัวและค่า

4.ประโยชน์ที่คาดว่าจะได้รับ

จากผลลัพธ์จะเห็นว่า เราไม่ได้สีแดงทั้งหมด เพราะ ว่าตรงส่วนนั้นอาจเกิดจากค่า H ของสีส้มถ้าดูจากรูปล่างที่ H = 0 มันจะออกแดงๆส้มๆ บวกกับการปรับค่า S กับ V ก็จะทำให้ได้ Pixel บริเวณที่ขาดหายไป
ซึ่งตรงนี้ก็เป็นหนึ่งในข้อเสียของ HSV color model มีข้อดีก็ต้องมีข้อเสียนะครับ แต่เราแก้ไขได้ด้วยการ หาช่วงของสีเหลืองเพิ่ม แล้วเอามารวมกันลองไปทำกันดูนะครับ ตอนรวมให้ใช้ resultRed + resultYellow ได้เลยนะครับ โดย resultRed กับ resultYellow คือ ผลลัพธ์จาก function inRange

5.ความรู้ที่เกี่ยวข้อง

Module ที่ใช้
numpy as np np.array
argparse argparse.ArgumentParser
cv2 cv2.imread

# import the necessary packages
import numpy as np
import argparse
import cv2
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", help = "path to the image")
args = vars(ap.parse_args())
# load the image
image = cv2.imread("test.jpg")
# define the list of boundaries
boundaries = [    
([17, 15, 100], [50, 56, 200]),   
([86, 31, 4], [220, 88, 50]),   
([25, 146, 190], [62, 174, 250]),    
([103, 86, 65], [145, 133, 128])]
# loop over the boundaries
for (lower, upper) in boundaries:            
# create NumPy arrays from the boundaries    
lower = np.array(lower, dtype = "uint8")    
upper = np.array(upper, dtype = "uint8")        
# find the colors within the specified boundaries and apply        
# the mask    
mask = cv2.inRange(image, lower, upper)    
output = cv2.bitwise_and(image, image, mask = mask)        
# show the images    cv2.imshow("images", np.hstack([image, output]))   
 cv2.waitKey(0)

6.ผลการดำเนินงาน
หากสภาพแวดล้อมของคุณได้รับการกำหนดค่าอย่างถูกต้อง (หมายความว่าคุณได้ติดตั้ง OpenCV ที่มีการผูก Python ไว้) คุณจะเห็นสิ่งนี้เป็นภาพผลลัพธ์ของคุณ:

อย่างที่คุณเห็นตลับโปเกมอนสีแดงตรวจพบได้ง่าย!

ตอนนี้เรามาลองใช้สีน้ำเงินกัน:

ไม่ไม่มีปัญหา!

และเรื่องราวที่คล้ายกันสำหรับรุ่น Yellow:

สุดท้ายนี้ยังพบโครงร่างของตลับเกมบอยสีเทา:

7.สรุปผลการนำเสนอแนะ

โดยรวมของโปรแกรมถือว่าเป็นไปตามเป้าหมาย แต่อาจจะมีปัญหาติดขัดเล็กน้อย อย่างเช่น ตัว Code ในการใช้เขียน จะไม่เหมือนกันในแต่ละเวอร์ชั่นของ Python การลงโมดูล (Module) เนื่องจากตัว Python ในเวอร์ชั่นใหม่ๆ จะยังไม่รองรับโมดูล (Module) บางตัว
ในบล็อกโพสต์นี้ฉันได้แสดงวิธีตรวจจับสีโดยใช้ OpenCV และ Python ในการตรวจจับสีในภาพสิ่งแรกที่คุณต้องทำคือกำหนดขีด จำกัด บนและล่างสำหรับค่าพิกเซลของคุณ เมื่อคุณกำหนดขีด จำกัด บนและล่างของคุณแล้วคุณจะโทรไปยังเมธอด cv2.inRange ซึ่งจะส่งคืนมาสก์โดยระบุพิกเซลที่อยู่ในช่วงบนและล่างที่คุณระบุ ในที่สุดเมื่อคุณมีมาสก์แล้วคุณสามารถนำไปใช้กับภาพของคุณโดยใช้ฟังก์ชัน cv2.bitwise_and รถไฟของฉันอยู่ห่างจากบ้านเพียงไม่กี่สถานีดังนั้นฉันจึงควรสรุปโพสต์นี้ ฉันหวังว่าคุณจะพบว่ามีประโยชน์! และหากคุณมีคำถามเช่นเคยอย่าลังเลที่จะแสดงความคิดเห็นหรือส่งข้อความถึงฉัน

8.ข้อมูลอ้างอิง

8.1 แหล่งข้อมูลและหลักการทำงาน

Share

You may also like...

Leave a Reply