Bài viết tiếp theo trong series Tự học và phát triển ứng dụng thực tế AI, ML, DL, DS chúng ta sẽ cùng nhau viết một ứng dụng cảnh báo người lạ đột nhập.
Trong bài này chúng ta sẽ áp dụng kỹ thuật xử lý ảnh trong OpenCV và ngôn ngữ lập trình Python để thực hiện nhận diện đối tượng với hình ảnh đưa vào từ camera hoặc webcam.
Ý tưởng bài toán
Ý tưởng khá đơn giản, chúng ta sẽ dùng OpenCV vẽ cố định vùng cần quan sát trên khung hình được lấy từ camera. Nếu có đối tượng di chuyển vào khu vực đã xác định, ta sẽ nhận diện và phát tín hiệu cảnh báo.
Thuật toán xử lý ảnh phát hiện đối tượng di chuyển trong ảnh
Một phương pháp đơn giản chúng ta sẽ sử dụng là Background Subtraction hay thuật toán trừ nền. Thuật toán Background Subtraction là một kỹ thuật phổ biến được sử dụng rộng rãi để phát hiện các đối tượng chuyển động trong ảnh. Trong phương pháp này chúng ta cần sử dụng video được quay từ một camera cố định.
Chúng ta dùng các hàm sau trong thư viện OpenCV để xử lý:
- cv2.cvtColor: Chuyển đổi không gian màu của ảnh đầu vào
- cv2.GaussianBlur: Làm mờ ảnh sử dụng thuật toán Gaussian
- cv2.absdiff: Tính toán sự khác biệt tuyệt đối giữa 2 ảnh đầu vào
- cv2.threshold: Áp dụng một ngưỡng cố định cho ảnh
- cv2.dilate: Áp dụng thuật toán giãn nở ảnh
Viết chương trình ứng dụng AI cảnh báo người lạ đột nhập với OpenCV và Python
Đầu tiên chúng ta import một số packages cần thiết
1 2 3 4 5 |
import argparse import datetime import cv2 import imutils import pyglet |
Sau đó, chúng ta thiết lập các tham số của chương trình
1 2 3 4 5 |
ap = argparse.ArgumentParser() ap.add_argument("-v", "--video", type=str, default='0', help="Nguồn video mặc định 0 là sử dụng webcam") ap.add_argument("-a", "--min-area", type=int, default=300, help="Kích thước nhỏ nhất của đối tượng") ap.add_argument("-b", "--background", type=str, default=None, help="Ảnh background") args = vars(ap.parse_args()) |
Đọc video và khởi tạo background
1 2 3 4 5 6 7 8 9 10 11 12 |
if args['video'] == '0': capture = cv2.VideoCapture(0) else: capture = cv2.VideoCapture(args['video']) first_frame = None if args['background'] is not None: first_frame = cv2.imread(args['background']) # Chuyển ảnh đầu vào về ảnh xám first_gray = cv2.cvtColor(first_frame, cv2.COLOR_BGR2GRAY) # Làm mờ ảnh first_gray = cv2.GaussianBlur(first_gray, (21, 21), 0) |
Vẽ phạm vi quan sát đối tượng di chuyển vào
1 |
top_left, bottom_right = (50, 200), (400, 280) |
Bây giờ là phần xử lý chính.
Lặp lần lượt từng frame của video:
B1: Resize ảnh về kích thước cố định
B2: Tạo ảnh background nếu không được truyền vào
B3: Tính sự khác biệt giữa ảnh hiện tại và ảnh background
B4: Sử dụng threshold để chuyển ảnh về dụng nhị phân
B5: Thực hiện giãn nở ảnh để làm rõ các cùng vùng màu trắng trong ảnh
B6: Xác định đường bao cho các đối tượng thu được
B7: Kiểm tra đối tượng có nằm trong khu vực quan sát hay không
B8: Hiện cảnh báo lên hình và phát tín hiệu cảnh báo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
idx = 0 # Lặp lần lượt từng frame của video while True: ret, frame = capture.read() if frame is None: break text = "An toan" # Resize ảnh về kích thước cố định frame = imutils.resize(frame, width=500) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(gray, (21, 21), 0) # Tạo ảnh background nếu không được truyền vào if first_frame is None: first_frame = frame first_gray = cv2.cvtColor(first_frame, cv2.COLOR_BGR2GRAY) first_gray = cv2.GaussianBlur(first_gray, (21, 21), 0) # Tính sự khác biệt giữa ảnh hiện tại và ảnh background frameDelta = cv2.absdiff(first_gray, gray) # Sử dụng threshold để chuyển ảnh về dụng nhị phân thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1] # Thực hiện giãn nở ảnh để làm rõ các cùng vùng màu trắng trong ảnh thresh = cv2.dilate(thresh, None, iterations=2) # Xác định đường bao cho các đối tượng thu được cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) # Xác định vùng cần kiểm tra cv2.rectangle(frame, top_left, bottom_right, (0, 255, 0), 2) for c in cnts: # Loại bỏ các đối tượng có kích thước nhỏ if cv2.contourArea(c) < args["min_area"]: continue # Lấy tọa độ của hình chữ nhật bao quanh đối tượng (x, y, w, h) = cv2.boundingRect(c) # Xác định tâm của đối tượng center_x = x + w / 2 center_y = y + h / 2 # Kiểm tra đối tượng có nằm trong khu vực quan sát hay không logic = top_left[0] < center_x < bottom_right[0] and top_left[1] < center_y < bottom_right[1] if logic: cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2) text = "Co xam nhap" # Hiện cảnh báo lên hình cv2.putText(frame, "Canh bao: {}".format(text), (150, 20),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2) # Phát báo động music = pyglet.resource.media('alert.wav') music.play() # show the frame and record if the user presses a key cv2.imshow("Camera an ninh", frame) cv2.imwrite('images/{}_result.jpg'.format(idx), frame) idx += 1 keyboard = cv2.waitKey(30) if keyboard == 'q' or keyboard == 27: break cv2.destroyAllWindows() |
Chúng ta cùng xem kết quả nhé
1 |
python3 detector.py -v video.mp4 |
Như vậy mình đã giới thiệu cho các bạn một phương pháp đơn giản sử dụng các thuật toán xử lý ảnh để phát hiện người lạ đột nhập. Để chính xác hơn trong việc phát hiện đối tượng là người chúng ta có thể áp dụng 1 số kỹ thuật học sâu (Deep Learning).
Chúc các bạn thành công
Good tutorial
Có thể bảo vào model YOLO v8 để detect không ạ