Top Ad unit 728 × 90


Phát hiện nhận dạng biển báo giao thông dùng OpenCV

Chào các bạn, ở bài này chúng ta sẽ viết một chương trình đơn giản để nhận dạng biển báo giao thông.

Chúng ta sẽ nhận dạng một số biển cơ bản như hình dưới.


Đầu tiên chúng ta sẽ thiệt lập một hàm để tìm màu chủ đạo.
def get_dominant_color(image, n_colors):
    pixels = np.float32(image).reshape((-1, 3))
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 200, .1)
    flags = cv2.KMEANS_RANDOM_CENTERS
    flags, labels, centroids = cv2.kmeans( pixels, n_colors, None, criteria, 10, flags)
    palette = np.uint8(centroids)
    return palette[np.argmax(itemfreq(labels)[:, -1])]
Tiếp theo tiến hành lấy frame hình ảnh từ Camera.
def onMouse(event, x, y, flags, param):
    global clicked
    if event == cv2.EVENT_LBUTTONUP:
        clicked = True
cameraCapture = cv2.VideoCapture(0)
cv2.namedWindow('camera')
cv2.setMouseCallback('camera', onMouse)
# Read and process frames in loop
success, frame = cameraCapture.read()
while success and not clicked:
    cv2.waitKey(1)
    success, frame = cameraCapture.read()

Đổi từ ảnh màu sang gray để tăng tốc độ tính toán xử lý ảnh
Chúng ta cần tìm circles trong BGR và GRAY .
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

Sau đó chúng ta làm mờ để loại bỏ những vòng tròn nhiễu không phải biển báo.
    img = cv2.medianBlur(gray, 37)
Tiếp theo openCV có hỗ trợ hàm HoughCircles để tìm hình tròn. Thông số quan trọng nhất ở đây là minDist (trong ví dụ này mình đặt là 50) và param{1,2}. minDist thể hiện khoảng cách giữa trung tâm của các vòng tròn được phát hiện. Tăng thông số param1 sẽ tăng số đường tròn phát hiện, tăng param2 sẽ tăng thể nhiều vòng tròn sai, không mong muốn)
    circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT,
                              1, 50, param1=120, param2=40)

    if not circles is None:
        circles = np.uint16(np.around(circles))
        #Lọc vòng tròn lớn nhất, chúng ta không muốn detect các biển báo ở xa
        # chỉ lấy biến báo gần nhất.
        max_r, max_i = 0, 0
        for i in range(len(circles[:, :, 2][0])):
            if circles[:, :, 2][0][i] > 50 and circles[:, :, 2][0][i] > max_r:
                max_i = i
                max_r = circles[:, :, 2][0][i]
        x, y, r = circles[:, :, :][0][max_i]
 
  # Chúng ta tiến hành cắt các ô vuông bên trong biển báo để kiểm tra và nhận dạng.


        if y > r and x > r:
            square = frame[y-r:y+r, x-r:x+r]
            dominant_color = get_dominant_color(square, 2)
            if dominant_color[2] > 100:
                # Biển Stop, nên mình tìm màu chủ đạo là màu đỏ thì sẽ nhận ra biển STOP
                print("STOP")
            elif dominant_color[0] > 80:
                # Ở đây có ba vùng trong biển báo, chúng ta sẽ so sánh màu chủ đạo để đưa ra nhận dạng
                zone_0 = square[square.shape[0]*3//8:square.shape[0]
                                * 5//8, square.shape[1]*1//8:square.shape[1]*3//8]
                zone_0_color = get_dominant_color(zone_0, 1)
                zone_1 = square[square.shape[0]*1//8:square.shape[0]
                                * 3//8, square.shape[1]*3//8:square.shape[1]*5//8]
                zone_1_color = get_dominant_color(zone_1, 1)
                zone_2 = square[square.shape[0]*3//8:square.shape[0]
                                * 5//8, square.shape[1]*5//8:square.shape[1]*7//8]
                zone_2_color = get_dominant_color(zone_2, 1)
                if zone_1_color[2] < 60:
                    if sum(zone_0_color) > sum(zone_2_color):
                        print("LEFT")
                    else:
                        print("RIGHT")
                else:
                    if sum(zone_1_color) > sum(zone_0_color) and sum(zone_1_color) > sum(zone_2_color):
                        print("FORWARD")
                    elif sum(zone_0_color) > sum(zone_2_color):
                        print("FORWARD AND LEFT")
                    else:
                        print("FORWARD AND RIGHT")
            else:
                print("N/A")
        for i in circles[0, :]:
            cv2.circle(frame, (i[0], i[1]), i[2], (0, 255, 0), 2)
            cv2.circle(frame, (i[0], i[1]), 2, (0, 0, 255), 3)
    cv2.imshow('camera', frame)

Mã nguồn: Tải Về Mã Nguồn.
Kênh Youtube: http://youtube.com/jackyle

Phát hiện nhận dạng biển báo giao thông dùng OpenCV Reviewed by Jacky on tháng 9 15, 2018 Rating: 5

5 nhận xét:

  1. from scipy.stats import itemfreq
    sao nó báo lỗi thư viện này vậy ad ????

    Trả lờiXóa
  2. anh ơi cái này là ko có db phải không ạ! với chỉ nhận dạng đưcọ biển tròn thôi phỉa ko ạ

    Trả lờiXóa
  3. ImportError: No module named 'cv2'
    Anh ơi em bị lỗi này làm sâ vậy anh

    Trả lờiXóa

All Rights Reserved by Cộng Đồng OpenCV © 2017
Edit bởi: Jacky Le | Youtube Channel: JACKY LE

Biểu mẫu liên hệ

Tên

Email *

Thông báo *

Được tạo bởi Blogger.