pythonนับรถอัจฉริยะ

ผู้เขียนบทความ : สุพรรษา ประทุมทอง

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

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

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

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

2.1 เพื่อตรวจจับยานพาหนะ

2.2 เพื่อตรวจนับจำนวนยานพาหนะ

2.3 เพื่อความสะดวกสบายต่อการทำงานต่อการนำข้อมูลดังกล่าวไปใช้สำหรับวางแผนประเมิน และวิเคราะห์การจราจร

3.ขอบเขต

3.1 ระบบถูกพัฒนาด้วยโปรแกรม Visual Studio Code

3.2 เป็นการตรวจนับจำนวนรถบนท้องถนน 

3.4 ตัวโปรแกรมได้ถูกพัฒนาโดยใช้ OpenCV , Numpy และภาษา Python ในการเขียน

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

4.1 สามารถตรวจนับยานพาหนะตามตำแหน่งที่ต้องการได้

4.2 สามารถตรวจนับจำนวนรถได้ทั้งขาเข้า และขาออก

4.3 สามรถตรวจจับยานพาหนะได้ทุกประเภท

4.4 สามารถนำข้อมูลที่ได้ไปทำการวิเคราะห์ และประเมินสภาพการจราจรในแต่ละพื้นที่ได้

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

5.1ภาษา Python
ภาษาโปรแกรม Python คือภาษาโปรแกรมคอมพิวเตอร์ระดับสูง โดยถูกออกแบบมาให้เป็นภาษาสคริปต์ที่อ่านง่าย  โดยตัดความซับซ้อนของโครงสร้างและไวยกรณ์ของภาษาออกไป ในส่วนของการแปลงชุดคำสั่งที่เราเขียนให้เป็นภาษาเครื่อง Python มีการทำงานแบบ Interpreter คือเป็นการแปลชุดคำสั่งทีละบรรทัด เพื่อป้อนเข้าสู่หน่วยประมวลผลให้คอมพิวเตอร์ทำงานตามที่เราต้องการ นอกจากนั้นภาษาโปรแกรม Python ยังสามารถนำไปใช้ในการเขียนโปรแกรมได้หลากหลายประเภท โดยไม่ได้จำกัดอยู่ที่งานเฉพาะทางใดทางหนึ่ง (General-purpose language) จึงทำให้มีการนำไปใช้กันแพร่หลายในหลายองค์กรใหญ่ระดับโลก เช่น Google, YouTube, Instagram, Dropbox และ NASA เป็นต้น

5.2 Open cv ในการนำ OpenCV มาใช้งานร่วมกับ Visual Studio C++ เพื่อใช้พัฒนาโปรแกรมนั้น เราจำเป็นต้องตั้งค่าให้กับโปรแกรม Visual Studio C++ ก่อน เพื่อระบุตำแหน่งของ Library ของ OpenCV ตำแหน่งของไฟล์ที่ต้องใช้ในโปรแกรม และตำแหน่งของ Source File ให้ตัวโปรแกรมทราบ และสามารถดึงมาใช้ได้

การนำไปใช้ประโยชน์ จากOpenCV ในมินิโปรเจคนี้

-ใช้เป็นเครื่องมือการประมาณในขณะเคลื่อนที่

-ระบบการจดจำท่าทาง

-การจัดการภาพเคลื่อนไหว

-จับการเคลื่อนไหวของวัตถุ

-วิเคราะห์แยกฉากหลัง

-ออปติคัลโฟลว์ (optical flow)

-อ่านเขียนวีดีโอ

หลักการและทฤษฎี

อาศัยหลักการประมวลผลภาพกับรูปร่างและโครงสร้างของภาพโดยนำคณิตสัณฐานวิทยา (MM : Mathematical Morphology) เพื่อประมวลผลภาพตามหลักทฤษฎีแลตติซ เป็น เทคนิคสำหรับการวิเคราะห์และประมวลผลโครงสร้างทางเรขาคณิตบนพื้นฐานของทฤษฎีเซต ทฤษฎีตาข่าย โครงสร้างของเครือข่ายและฟังก์ชั่นแบบสุ่ม นิยมนำมาใช้งานกับภาพดิจิตอล เพื่อวิเคราะห์พื้นผิว ขนาด รูปร่าง พื้นที่นูน การเชื่อมต่อโดยอาศัยตัวดำเนินการ 4 ลักษณะ เรียนSOLE จนใน Morphology = ลักษณะทางสัณฐานวิทยา

– การขยายภาพ (Dilation)

– การกร่อนภาพ (Erosion)

– การเปิดภาพ (Opening)

– การปิดภาพ (Closing)

***การประมวลผลภาพกับรูปร่างและโครงสร้างภาพเป็นเทคนิคของการ ประมวลผลภาพที่ขึ้นอยู่กับรูปร่าง ค่าของ Pixels ในภาพ Output ขึ้นอยู่กับการ เปรียบเทียบของ Pixels ที่สอดคล้องกันในภาพ Input กับพื้นที่ใกล้เคียง โดย เลือกขนาดและรูปร่างของพื้นที่ใกล้เคียงมาสร้างการดำเนินการทางรูปร่างและ โครงสร้างของภาพต่อไป

Morphology Operator

ภาพต้องพัฒนามาจากภาพไบนารี หรือ ภาพสีเทา (Gray scale)

การขยายภาพ (Dilation) => สำหรับตรวจสอบและขยายรูปทรงที่มีอยู่ในภาพ Input – ถ้าเป็นภาพสีเทา จะขยายภาพและเพิ่มความสว่างของวัตถุโดยใช้พื้นที่ใกล้เคียงสูงสุด – ถ้าเป็นภาพไบนารี จะขยายภาพและเชื่อมต่อพื้นที่ที่แยกออกจากกันด้วยช่องว่างที่มีขนาด เล็กกว่าองค์ประกอบโครงสร้างและเพิ่ม Pixels เข้าไปที่ขอบด้านนอกของแต่ละวัตถุในภาพ

การขยายภาพ

ภาพต้องพัฒนามาจากภาพไบนารี หรือ ภาพสีเทา (Gray scale)

การกร่อนภาพ (Erosion) => สำหรับลดขนาดของวัตถุและความผิดปกติเล็กๆ โดยลบ วัตถุที่มีรัศมีเล็กกว่าองค์ประกอบของโครงสร้าง – ถ้าเป็นภาพสีเทา จะลดขนาดวัตถุและลดความสว่างของวัตถุบนพื้นหลังสีเข้ม โดยใช้พื้นที่ใกล้เคียงต่ำสุด – ถ้าเป็นภาพไบนารี ลบวัตถุที่มีขนาดเล็กกว่าองค์ประกอบของโครงสร้างออกและลบ Pixels ที่ขอบด้านนอกออกจากวัตถุในภาพ

ภาพต้องพัฒนามาจากภาพไบนารี หรือ ภาพสีเทา (Gray scale)

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

การปิดภาพ (Closing) กระทำในทางตรงกันข้ามกับ Opening โดยเป็นการทำให้ Pixels ของภาพเชื่อมต่อกันมากขึ้น – การเปิดและ ปิดภาพเป็นการกำจัดสัญญานรบกวนในรูปร่างและโครงสร้างของภาพ การเปิด => กำจัดวัตถุขนาดเล็ก การปิด => กำจัดช่องโหว่เล็กๆและเชื่อมต่อ

รูป การนำมาประยุกต์ใช้

ขั้นตอนการติดตั้ง opencv-python เป็นมอดูลหนึ่งของไพธอนสามารถติดตั้งลงได้ง่ายโดยใช้ pip เหมือนมอดูลอื่นๆส่วนใหญ่

pip install opencv-python

5.3 Numpy เป็น library ที่ใช้ในการดำเนินการเกี่ยวกับ array ใช้คำนวณทางคณิตศาสตร์และวิทยาศาสตร์ โดยมีคำสั่งพร้อมใช้งานจำนวนมากมาย เป็นโมดูลส่วนเสริมของ Python ที่มีฟังก์ชัน เกี่ยวกับคณิตศาสตร์และการคำนวณต่างๆ มาให้ใช้งาน โดยทั่วไปจะ เกี่ยวกับการจัดการข้อมูลชุด (Array) ขนาดใหญ่และเมทริกซ์ ซึ่งในโปรเจคนี้มีวามสำคัญมากในการใช้ตัว Numpyค่ะ

– NumPy (Numeric Python) เป็นโมดูลส่วนเสริมของ Python มีฟังก์ชั่น เกี่ยวกับคณิตศาสตร์และการคำนวณต่างๆ มาให้ใช้งาน ใช้การจัดการข้อมูลชุด (Array) ขนาดใหญ่และเมทริกซ์ (สำหรับสร้างตาราง Matrix ในการประมวลผลภาพ) – Arrays ของ NumPy มีลักษณะคล้ายกับ list แต่สมาชิกทุกตัวใน arrayจะต้องเป็น ข้อมูลชนิดเดียวกัน โดยทั่วไปแล้วข้อมูลที่เก็บจะเป็นตัวเลขเช่น int หรือ float คล้าย list แต่ทำไมใช้ Array ??? Arrays มีความสามารถในการดำเนินการเกี่ยวกับข้อมูลที่เป็นตัวเลขจำนวนมากๆ ได้อย่างรวดเร็วและมีประสิทธิภาพมากกว่า list

การติดตั้ง Numpy เข้าไป install ใน command line โดยป้อนคำสั่ง python -m pip install numpy และกด Enter

python -m pip install numpy

6.การดำเนินงาน

รูปแบบของโค๊ด

import cv2 
import numpy as np
zmin_contour_width=50  #40
min_contour_height=50  #40
offset=10       #10
line_height=550 #550
matches =[]
cars=0
def get_centroid(x, y, w, h):
    x1 = int(w / 2)
    y1 = int(h / 2)

    cx = x + x1
    cy = y + y1
    return cx,cy
    #return (cx, cy)

#cap = cv2.VideoCapture(0) คือ ฟังก์ชันที่ใช้ในการอ่านไฟล์วิดีโอจากข้อมูลในคอมพิวเตอร์เก็บใส่ตัวแปร โดยในโปรแกรมนี้ใช้ตัวแปร 0 คืออ่านภาพวิดีโอมาเป็นขาวดำ
cap = cv2.VideoCapture('g.mp4')
#cap = cv2.VideoCapture('Relaxing highway traffic.mp4')

 

cap.set(3,1920)  #ตั้งค่า ขนาดของภาพ หรือคุณสมบัติต่างๆได้อีกมากมาย โดยการใช้คำสั่ง cap.set(propId, value)
cap.set(4,1080)

if cap.isOpened():  #ตรวจสอบว่ามีการเริ่มต้นหรือไม่cap.isOpened () ret,frame1 = cap.read()  #cap.read () ส่งคืนค่า (True / False) ถ้าอ่าน frame ถูกต้องจะเป็น True คุณจึงตรวจสอบตอนท้ายของวิดีโอได้โดยตรวจสอบค่าส่งคืน
else:
    ret = False
ret,frame1 = cap.read()
ret,frame2 = cap.read()

while ret: 
    d = cv2.absdiff(frame1,frame2) #ต้องการเอาภาพมาเทียบแล้วหักลบกันโดยหาส่วนต่าง ซึ่งทำได้โดยฟังก์ชัน cv2.absdiff()
    grey = cv2.cvtColor(d,cv2.COLOR_BGR2GRAY) #แปลงภาพสีเป็นขาวดำ แปลงภาพเป็นไบนารี่
    #blur = cv2.GaussianBlur(grey,(5,5),0)
    blur = cv2.GaussianBlur(grey,(5,5),0) #เบลอภาพเพื่อลบนอยท์
    #ret , th = cv2.threshold(blur,20,255,cv2.THRESH_BINARY)
    ret , th = cv2.threshold(blur,20,255,cv2.THRESH_BINARY) 
    dilated = cv2.dilate(th,np.ones((3,3)))
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2, 2))

        # Fill any small holes
    closing = cv2.morphologyEx(dilated, cv2.MORPH_CLOSE, kernel) #ฟังก์ชั่นนี้จะเป็นการลบ Noises
    contours,h = cv2.findContours(closing,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) #แสดงตำแหน่งจุดบนเส้น ซึ่งสามารถใช้ผลที่ได้จาก cv2.findContours() 
    for(i,c) in enumerate(contours):
        (x,y,w,h) = cv2.boundingRect(c) #ต้องการหาขอบเขตว่าเส้นเค้าโครงนี้มีค่าต่ำสุดตั้งแต่เท่าไหร่ถึงเท่าไหร่อาจใช้ฟังก์ชัน cv2.boundingRect()
        contour_valid = (w >= min_contour_width) and (
            h >= min_contour_height)
  
        if not contour_valid:
            continue
        cv2.rectangle(frame1,(x-10,y-10),(x+w+10,y+h+10),(255,0,0),2)  #เป็นสี่เหลี่ยมนับรถ 

        cv2.line(frame1, (0, line_height), (1200, line_height), (0,255,0), 2) #วาดเส้นโดยมีความหนา  การวาดรูปทรงเรขาคณิต
        centroid = get_centroid(x, y, w, h)
        matches.append(centroid)
        cv2.circle(frame1,centroid, 5, (0,255,0), -1)  #การวาดรูปทรงเรขาคณิต
        cx,cy= get_centroid(x, y, w, h)
        for (x,y) in matches:
            if y<(line_height+offset) and y>(line_height-offset):
                cars=cars+1
                matches.remove((x,y))
                print(cars)

    cv2.putText(frame1, "Total Cars Detected: " + str(cars), (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 1, #cv2.putTextระบุตำแน่งอักษรหรือข้อความที่จะเขียน
                    (0, 170, 0), 2)

    cv2.putText(frame1, "MechatronicsLAB.net", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1,
                    (255, 170, 0), 2)



    #cv2.drawContours(frame1,contours,-1,(0,0,255),2)


    cv2.imshow("Original" , frame1)
    cv2.imshow("Difference" , th)
    if cv2.waitKey(1) == 27: #ในการรอกดปุ่มจาก keyboard รูปแบบของฟังก์ชันจะเป็น cv2.waitkey(time) 27คือเวลา (เป็นคำสั่งสำหรับรอคีย์บอร์ดตามที่กำหนดเวลาไว้ในหน่วยมิลลิวินาที ถ้าใช้ 0 จะไม่มีการรอ )
        break
    frame1 = frame2
    ret , frame2 = cap.read()
#print(matches)    
cv2.destroyAllWindows() #เป็นคำสั่งสำหรับใช้โชว์วัตถุที่กระทำด้วย OpenCV กับ Python
cap.release() #แสดงจากกล้อง

7.ผลการดำเนินงาน

การนำมาใช้จริง

ผลการทดลองการนำไปใช้จริง

8.ข้อเสนอแนะ

8.1 ควรติดตั้งกล้องที่มีความนิ่งมั่นคง ไปไม่ขยับไปมาจะดีสุด

8.2 ควรเป็นกล้องที่มีความละเอืยดของภาพสูง เพื่อที่จะประมวลผลได้ถูกต้องแม่นยำขึ้น

8.3 ควรถ่ายจากมุมสูง เพื่อความครอบคลุมในการตรวจนับได้อย่างทั่วถึง

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

Source Code ที่นำมาใช้งาน https://github.com/celalaygar/car-counting-with-python/find/master

ทฤษฎีในการศึกษาข้อมูลเพิ่มเติมจากแหล่ง YouTube

ข้อมูลอ้างอิงเกี่ยวกับ numpy https://www2.cs.science.cmu.ac.th/courses/204101/lib/exe/fetch.php?media=w13-lec_-numpy.pdf

https://medium.com/@phongyanonyangen/%E0%B9%83%E0%B8%8A%E0%B9%89-numpy- %E0%B8%89%E0%B8%9A%E0%B8%B1%E0%B8%9A%E0%B8%9E%E0%B8%B7%E0%B9%89%E0%B8%99%E0%B8%90%E0%B8%B2%E0%B8%99-e5190ab85251


Share

You may also like...

Leave a Reply