Phát hiện đối tượng – P1: lý thuyết

haarlike

Phát hiện đối tượng là để trả lời câu hỏi: “Đối tượng cần tìm có ở trong ảnh hay không?” và “Nếu có thì nằm ở vị trí nào?”

Trong các phương pháp phát hiện đối tượng hiện nay có Haar cascade là phương pháp phổ biến nhất. Quy trình bao gồm:

Bước 1: Dùng tool của Opencv cung cấp để rút trích đặc trưng của đối tượng (gọi là haar-like) ghi vào tập dữ liệu (*.xml). Đó là các đặc trưng đường chéo, đường ngang, đường dọc của đối tượng.

Bước 2: Viết chương trình để tìm đối tượng. Sau khi load các đặc trưng từ file xml đã huấn luyện, thuật toán của OpenCV sẽ lần lượt quét qua các vùng trên ảnh để tìm đối tượng. Đối tượng nào có đặc trưng giống với tập dữ liệu & thoả mãn các tham số thì xem như đó là đối tượng cần tìm.

Bước 1: Rút trích đặc trưng

Bước này còn được gọi là huấn luyện (training)

Bạn cần chuẩn bị 2 bộ ảnh, một bộ ảnh có chứa đối tượng gọi là ảnh dương. Bộ còn lại là những ảnh bất kỳ không chứa đối tượng gọi là ảnh âm. Số lượng ảnh âm & dương càng nhiều thì độ chính xác càng cao & thời gian huấn luyện càng lâu.

Khi training, chương trình sẽ rút ra đặc trưng rồi so sánh với các ảnh âm, nếu đặc trưng đó được tìm thấy trong ảnh âm thì đặc trưng đó không phù hợp.

Ví dụ
Để phát hiện biển số xe, bạn cần khoảng 2000 ảnh biển số & 1000 ảnh không chứa biển số. Ảnh không có biển số có thể là ảnh hoa lá cành, đồ vật bất kỳ...

Tiếp theo, bạn phải chỉ định rõ vị trí hình chữ nhật chứa đối tượng cần tìm và lưu vào file chỉ mục. Có 2 cách thực hiện:

    – Crop ảnh chỉ lấy vùng chữ nhật chứa đối tượng: file chỉ mục chỉ chứa tên file ảnh
    – Ghi lại thông số x y width height của vùng chữ nhật vào file: file chỉ mục gồm tên file ảnh, số vùng chữ nhật trong ảnh và các toạ độ x y width height

Mình có viết tool Object Locator để giúp bạn thực hiện bước trên

Khi đã có file chỉ mục, các bạn sẽ làm 2 bước để tạo tập dữ liệu (*.xml), thuật toán của 2 bước này được viết sẵn:
– Bước 1.1: dùng opencv_createsamples.exe tạo file vecto chứa ảnh thumbnail của vùng hình chữ nhật. Bước này nhanh, 2000 ảnh mất chưa tới 1 phút.
– Bước 1.2: dùng opencv_traincascade.exe lấy ảnh trong file vecto đặt ngẫu nhiên vào các ảnh âm để rút trích các đặc trưng. Bước này chậm, 2000 ảnh mất từ 1 ngày đến 1 tuần tuỳ theo độ chính xác các bạn yêu cầu.

Hoàn thành 2 bước này bạn sẽ có file xml

Bước 1.1 tạo file vecto

Đầu tiên các bạn tìm chương trình opencv_createsamples.exe trong lib Opencv theo đường dẫn opencv300\build\bin\Release và truyền các tham số sau:

-info file chỉ mục mà bạn đã tạo
-img khi bạn chỉ có 1 ảnh dương (như là logo cty chẳng hạn) thì bỏ qua tham số -info và truyền tên file ảnh vào đây
-vec file output cho bước tiếp theo
-bg file ảnh âm khi bạn chỉ có 1 ảnh dương
-num số lượng file ảnh dương
-bgcolor khi bạn không chỉ định ảnh âm thì có thể chỉ định 1 màu để làm ảnh âm
-inv -randinv -bgthresh -maxidev -maxxangle -maxyangle -maxzangle các tham số để tạo thêm các ảnh ngẫu nhiên bằng cách xoay trong không gian 3 chiều
-show hiện ảnh trong quá trình tạo mẫu
-w chiều rộng của mẫu được tạo
-h chiều cao của mẫu được tạo

Ví dụ: opencv_createsamples.exe -vec D:\bienso.vec -info D:\plate_image\positive\location.txt -num 2000 -w 40 -h 30
OpenCV sẽ tạo file D:\bienso.vec có chứa 2000 ảnh thumbnail, mỗi ảnh có kích thước 40 x 30 pixels.

Bước 1.2 huấn luyện

train cascade

opencv_traincascade

Các bạn lấy file opencv_traincascade.exe truyền các tham số sau (do nhiều tham số nên mình chỉ ghi các tham số quan trọng):
-data Thư mục rỗng dành để chứa các step và các file tạm trong quá trình huấn luyện, file xml thu được cũng nằm trong này
-vec file vec bạn tạo ở bước 1.1
-bg file text chứa danh sách các file ảnh âm
-numPos số lượng ảnh dương
-numNeg số lượng ảnh âm
-numStage số lượng bước huấn luyện bạn muốn, càng lớn (14 -> 20) thì thời gian huấn luyện càng lâu và kết quả càng chính xác
-w chiều rộng của mẫu được tạo (ở bước 1.1 bao nhiêu thì ở đây cũng vậy)
-h chiều cao của mẫu được tạo (ở bước 1.1 bao nhiêu thì ở đây cũng vậy)
-minHitRate tỉ lệ chính xác của ảnh dương. ,
-maxFalseAlarmRate tỉ lệ cho phép sai số tối đa của ảnh âm.

Ví dụ: opencv_traincascade.exe -data D:\output -vec D:\bienso.vec -bg D:\plate_image\negative\list.txt -numPos 2000 -numNeg 1000 -numStage 20 -minHitRate 0.995 -maxFalseAlarmRate 0.5 -w 40 -h 30
Chương trình sẽ tạo file D:\output\cascade.xml chứa các đặc trưng của biển số xe. minHitRate=0.995 nghĩa là phải đúng 995/1000 ảnh. maxFalseAlarmRate=0.5 nghĩa là cứ mỗi 1000 ảnh chỉ được detect nhầm tối đa 500 ảnh.

Các file xml được huấn luyện sẵn nằm trong lib opencv theo đường dẫn: opencv300\sources\data\haarcascades hoặc các bạn có thể search trên Internet

Bước 2: Sử dụng tập dữ liệu để phát hiện đối tượng

Trước khi thực hiện thuật toán phát hiện đối tượng, ảnh phải chuyển sang ảnh xám (gray). Đồng thời cũng câng bằng sáng (equalize hist) để ảnh được đồng nhất về độ tương phản, không bị ảnh hưởng bởi ánh sáng môi trường.

OpenCV sẽ quét qua toàn bộ ảnh để so sánh với tập dữ liệu. Lần đầu tiên sẽ lấy hình chữ nhật kích thước bằng max-size được chỉ định (hoặc bằng kích thước ảnh). Sau đó thu nhỏ lại theo tỉ lệ được chỉ định rồi lại so sánh với tập dữ liệu, cứ như thế cho đến khi vùng quét bằng kích thước min-size thì dừng.


Để sử dụng, bạn cần load data từ file xml, sau đó dùng hàm detectMultiScale(const Mat& image, vector& objects, double scaleFactor=1.1, int minNeighbors=3, int flags=0, Size minSize=Size(), Size maxSize=Size()) để tìm đối tượng trong ảnh. Các tham số truyền vào bao gồm:
image: ảnh input
objects: kết quả trả về là các hình chữ nhật
scaleFactor tỉ lệ vùng chữ nhật được thu nhỏ sau mỗi lần quét (default là 1.1)
minNeighbors số khung hình chữ nhật trùng nhau tối thiểu để được xem là 1 đối tượng (default là 3)
flags phương thức quét
minSize và maxSize: kích cỡ tối thiểu, kích cỡ tối đa.

Hình bên dưới là test detect nhầm biển số xe hơi. Mặc dù đó không phải là biển số nhưng có đủ đặc trưng khi huấn luyện thì cũng được xem là biển số.
bugorfeature

Đọc thêm

Phần 2: thực hành: hướng dẫn các bước cụ thể để thực hành huấn luyện tạo file xml đặc trưng và viết chương trình thử nghiệm.

Phần 3: hỏi đáp Chia sẻ các kinh nghiệm và giải đáp thắc mắc của các bạn.

Các file xml được huấn luyện sẵn có khá nhiều trên mạng, mình có tổng hợp lại trong bài Tổng hợp data xử lý ảnh

25 Responses to Phát hiện đối tượng – P1: lý thuyết

  1. Hi anh ! Cảm ơn bài viết của anh ! :D, em cũng có làm và nó nhận diện khá ổn! Nhưng vấn đề của em là: Em đang nhận diện đối tượng là người, nhưng không chỉ là người đi bình thường, mà còn người già đi khom, người đang ngồi đang nằm.
    Em nghĩ là mình train cho hắn tất cả những hình người đang đứng, đang đi, đi khom, ngồi nằm cho hắn luôn! Mà em thấy độ chính xác nó không có cao! Anh có thể chia sẻ gì thêm không ạ ? 😀 Em cảm ơn anh nhiều ^^

    • vohungvi says:

      Để chính xác thì bạn set minHitRate bằng 0.999999 (default là 0.99).

      Để có thể phát hiện nhiều hình dáng thì phải có tập mẫu đủ lớn, mỗi hình dạng tầm 1000 ảnh

  2. Hiep Khau says:

    Chào bạn @vohungvi
    Cho mình hỏi – Có thể chạy opencv_createsamples.exe trực tiếp tất cả ảnh trong thư mục không. Hay bắt buộc phải tìm từng điểm đặc trưng của anh rồi lưu vào location.txt. Mấy cái icon của mình nguyên ảnh icon nó là điểm đặt trưng rồi nên mình cũng k dùng tool để định vị. Các cách nào để nó chạy luôn mấy ảnh icon không bạn.

    Cảm ơn

    • vohungvi says:

      Ý bạn là phát hiện các icon trong ảnh? Như vậy thì được vì đối tượng để train đã được loại bỏ dữ liệu không cần thiết

    • Hiep Khau says:

      Ảnh của mình có size 12×28 tương ứng với Icon luôn – Mình có 1000 ảnh nên k rút trích đặc trưng từng ảnh bằng tool được

    • vohungvi says:

      Tương ứng với icon thì được rồi.

      Còn 1000 ảnh là chuyện bình thường thôi bạn, vài ngàn ảnh vẫn phải làm

  3. Chuc Tran says:

    Em chào anh ạ!
    Anh ơi, anh có dữ liệu ảnh dương của biển số xe ô tô không ạ. Cho em xin với ạ

  4. anh ơi em làm theo cơ mà bị lỗi anh ạ . Info file name: C:\opencv\My.Project\GreenParking\location.txt
    Img file name: (NULL)
    Vec file name: C:\opencv\My.Project\bienso.vec
    BG file name: (NULL)
    Num: 518
    BG color: 0
    BG threshold: 80
    Invert: FALSE
    Max intensity deviation: 40
    Max x angle: 1.1
    Max y angle: 1.1
    Max z angle: 0.5
    Show samples: FALSE
    Width: 40
    Height: 30
    Max Scale: -1
    RNG Seed: 12345
    Create training samples from images collection…
    OpenCV: terminate handler is called! The last OpenCV error is:
    OpenCV(4.0.0-alpha) Error: Assertion failed (0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows) in cv::Mat::Mat, file C:\build\master_winpack-build-win64-vc14\opencv\modules\core\src\matrix.cpp, line 465

  5. dạ vâng . anh phê duyệt cho em vào nhóm với

  6. chào bạn . bạn giúp mình lỗi này đc k
    E:\opencv\opencv\build\x64\vc14\bin>opencv_createsamples -vec C:\bienso.vec -info C:\GreenParking\location.txt -num 1000 -w 40 -h 30
    Info file name: C:\GreenParking\location.txt
    Img file name: (NULL)
    Vec file name: C:\bienso.vec
    BG file name: (NULL)
    Num: 1000
    BG color: 0
    BG threshold: 80
    Invert: FALSE
    Max intensity deviation: 40
    Max x angle: 1.1
    Max y angle: 1.1
    Max z angle: 0.5
    Show samples: FALSE
    Width: 40
    Height: 30
    Max Scale: -1
    RNG Seed: 12345
    Create training samples from images collection…
    Unable to open file: C:\bienso.vec
    Done. Created 0 samples

    • vohungvi says:

      có thể là bạn để trong ổ C nên không có quyền tạo file, bạn chuyển sang ổ D xem thử

  7. Nam Phương says:

    A ơi, e xài OpenCV 4.0.0 nhưng tìm hoài không thấy 2 file opencv_createsample.exe và opencv_traincascade.exe

    • vohungvi says:

      sử dụng phiên bản opencv cũ hơn sẽ có, mình đang sử dụng 3.4.2

  8. E chào anh . E đang là đề tài tốt nghiệp nhận lỗi vết sước trên tấm nhựa thì cần học phần nào của opencv để làm được ạ? Em cảm ơn!

    • vohungvi says:

      Tùy vào loại vết xước, màu sắc, chất liệu của vật thể thì bạn lựa chọn thuật toán cho phù hợp:
      – Nếu vết xước lớn, có hình dạng dễ nhìn thì sử dụng contour
      – Nếu vết xước tạo màu khác biệt (như làm xước sơn) thì sử dụng HSV
      – …
      Tốt nhất là bạn vào group upload hình vết xước để mọi người hỗ trợ https://www.facebook.com/groups/thigiacmaytinh

    • Anh cho em hỏi là sau khi mình có kêt quả xử lí ảnh rồi. Em muốn giao tiếp giữa opencv với 1 vi điều khiển (arduino) thì làm thế nào ạ?

    • vohungvi says:

      Bản chất của việc gửi dữ liệu tới Arduino là gửi dữ liệu kiểu serial tới cổng COM. Trong example của Arduino có phần 04.Communication, bạn vào đó tìm hiểu cách nhận dữ liệu của Arduino. Còn gửi dữ liệu thì bạn tìm theo từ khóa như
      c++ send serial data arduino, ví dụ như bài: https://blog.manash.me/serial-communication-with-an-arduino-using-c-on-windows-d08710186498

      Còn nếu không sử dụng được để mình viết 1 bài về giao tiếp cơ bản

    • Em đã copy code cũng như làm theo 1 một số hướng dẫn nước ngoài nhưng cái visual 2015 nó không chạy được. Anh có thể gửi cho em 1 bài giao tiếp cơ bản c++ với arduino được không ạ (gmail:phungducdung97@gmail.com)? em cảm ơn rất nhiều!!!

      Anh cho em hỏi làm thêm phần giao diện trên c++ kết hợp với xử lí ảnh thì làm thế nào ạ? em biết nhiều người dùng c#(hạn chế về open cv) và dùng MFC(khó hiểu ạ). Anh có hướng nào không ạ? em cảm ơn!!

    • vohungvi says:

      Để mình viết 1 bài về kết nối cơ bản với Arduino bằng c++, khi nào viết xong sẽ gửi email cho bạn hay. Còn giao diện thì tốt nhất làm bằng C#, viết code xử lý bằng C++ và dùng CLR làm cầu nối. Bạn tham khảo bài này https://thigiacmaytinh.com/tao-ung-dung-opencv-bang-c/

  9. opencv_createsamples.txt -vec D:\bienso.vec -info D:\plate_image\positive\location.txt -num 2000 -w 40 -h 30
    Em xin hỏi cái lệnh này làm viết trong visual c++ hay trong file opencv_creatsaple.exe vậy?

Leave a Reply