Phát hiện vật thể – P2: thực hành

Trong bài này sẽ hướng dẫn các bạn nhận diện biển số xe máy. Đây là đề tài khá hấp dẫn vì mang tính thực tiễn cao, mặc dù đã nhiều người làm tuy nhiên độ chính xác chưa đạt được mức thương mại.

Để huấn luyện được Cascade thì các bạn nên đọc và hiểu hết lý thuyết trong phần 1 để dễ dàng thay đổi, tinh chỉnh các thiết lập, và cũng hiểu được các bộ dữ liệu mình chuẩn bị sẵn cho các bạn.

Nếu bạn không biết dùng command line, không biết cấu trúc của OpenCV thì bạn nên tìm hiểu trước khi đọc tiếp.

Các công cụ cần thiết

1. OpenCV 2.4.9 Đây là phiên bản ổn định (stable), các bạn có thể dùng phiên bản cao hơn vẫn ok
2. Tập dữ liệu dương: mình sử dụng bộ ảnh của công ty Green Parking. Trong file zip chứa 1749 ảnh
3. Tập dữ liệu âm: bao gồm 3000 hình ảnh bất kỳ không chứa biển số xe
4. Object locator: dùng để khoanh vùng đối tượng
5. Cascade analytics: dùng để đánh giá độ chính xác sau khi huấn luyện xong

Bắt đầu thực hiện

Các bước thực hiện như sau:

  1. Khoanh vùng đối tượng bằng tool Object locator
  2. Tạo tập ảnh sample bằng tool opencv_createsamples
  3. Huấn luyện bằng tool opencv_traincascade

Bước 1: Khoanh vùng đối tượng

Các bạn dùng tool Object locator vẽ hình chữ nhật bao lấy đối tượng, sau khi làm xong các bạn sẽ được file location.txt nằm trong thư mục chứa ảnh.

Mình đã tạo sẵn file location.txt cho các bạn. Và trong thư mục ảnh âm mình cũng có tạo file bg.txt chứa danh sách các file ảnh âm.

Trong thư mục ảnh âm có file _create_bg_file.bat. Các bạn chạy file đó để tạo ra file bg.txt có chứa đường dẫn tuyệt đối (để tránh lỗi tìm không thấy file)

Bước 2: Tạo tập ảnh samples

Dùng lệnh sau để tạo tập ảnh
opencv_createsamples.exe -info E:\GreenParking\location.txt -vec GreenParking.vec -w 30 -h 20 -num 1749

Ý nghĩa lệnh: bạn tạo file vecto tên là GreenParking.vec chứa 1749 ảnh crop biển số, mỗi ảnh có kích thước 30×20 pixels.

Bước 3: Huấn luyện

Tạo folder để chứa dữ liệu các bước huấn luyện, mình tạo folder E:\train

Dùng lệnh sau để huấn luyện
opencv_traincascade.exe -data E:\train -vec GreenParking.vec -bg E:\negatives\bg.txt -numPos 1700 -numNeg 3000 -w 30 -h 20 -featureType LBP

Ý nghĩa lệnh: huấn luyện để tạo file E:\train\cascade.xml, với 1700 ảnh dương và 3000 ảnh âm, với kích thước bằng kích thước samples đã được tạo, sử dụng LBP feature vì kết quả chính xác tương đương Haar feature nhưng lại nhanh hơn rất nhiều, phù hợp cho việc thử nghiệm.

Khi huấn luyện chương trình sẽ hiển thị như thế này

Lưu ý là khi tạo mẫu thì 1749 nhưng khi huấn luyện chỉ dùng 1700, điều đó giúp cho chương trình chạy không bị crash. Số lượng ảnh phải giảm đi tùy vào bộ ảnh.


Với câu lệnh như vậy mình huấn luyện trên máy CPU Intel core i5 2500 mất hơn 3 giờ

Kiểm tra độ chính xác bằng tool

Sau khi huấn luyện xong bạn sẽ được file E:\train\cascade.xml, dùng chương trình Cascade analytics để đánh giá độ chính xác. Mình đã test thử file kết quả thì độ phát hiện được 2848/3536 ảnh.

cascade.xml (22KB)
Download Cascade Analytics

Code detect object C++

Code detect object Python

https://github.com/opencv/opencv/blob/master/samples/python/facedetect.py

58 thoughts on “Phát hiện vật thể – P2: thực hành

    1. Mình mới vừa thêm link của chương trình Cascade Analytics và source code rồi nhé bạn

    2. em dùng đoạn code này của python thì vẫn khoanh đc vùng biển số

      import cv2

      # load classifier
      classifier = cv2.CascadeClassifier(‘cascade.xml’)

      # load image
      img = cv2.imread(‘oto.jpg’)

      # convert image to grayscale
      gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

      # detect faces
      faces = classifier.detectMultiScale(gray, 1.4, 3)

      # draw rectangles on image for every detected face
      for (x,y,w,h) in faces:
      img = cv2.rectangle(img, (x,y), (x+w,y+h), (455, 0, 0), 4)
      print(x, y, w, h)

      cv2.imwrite(‘test_sv.jpg’, img)
      cv2.imshow(‘out’, img)
      cv2.waitKey(0)
      cv2.destroyAllWindows()

  1. anh ơi cho em hỏi lỗi này là gì ạ:
    OpenCV Error: Insufficient memory (Failed to allocate 1073740800 bytes) in cv::OutOfMemoryError, file C:\builds\master_PackSlave-win64-vc12-shared\opencv\modules\core\src\alloc.cpp, line 52
    OpenCV Error: Assertion failed (u != 0) in cv::Mat::create, file C:\builds\master_PackSlave-win64-vc12-shared\opencv\modules\core\src\matrix.cpp, line 411

    1. dạ em thưa anh, nếu trong trường hợp em đang train em yêu cầu 18 Stage mà nó chỉ chạy đến Stage 13 xong ra thông báo như này thì đã train thành công chưa ạ
      Required leaf false alarm rate achieved. Branch training terminated.

    2. Vậy là train thành công rồi đó bạn, vào thư mục train sẽ thấy file cascade.xml. Còn lý do không đủ stage là do bộ ảnh dương của bạn quá ít (dưới 1000)

    3. anh ơi, cho em hỏi là khi em train thành công rồi nhưng khi chạy chương trình nó lại không thể load được file cascade.xml là sao ạ.Em đã chỉ rõ đường dẫn của file xml khi gọi hàm load rồi ạ.

  2. anh ơi cho em hỏi đây là lỗi gì ạ:

    F:\opencv\build\x64\vc15\bin>opencv_traincascade.exe -data E:\train -vec E:\bien.vec -bg C:\Users\DELL\Desktop\hoa-anh-am\bg.txt -numPos 49 -numNeg 25 -w 30 -h 20 -featureType LBP -mode ALL
    PARAMETERS:
    cascadeDirName: E:\train
    vecFileName: E:\bien.vec
    bgFileName: C:\Users\DELL\Desktop\hoa-anh-am\bg.txt
    numPos: 49
    numNeg: 25
    numStages: 20
    precalcValBufSize[Mb] : 1024
    precalcIdxBufSize[Mb] : 1024
    acceptanceRatioBreakValue : -1
    stageType: BOOST
    featureType: LBP
    sampleWidth: 30
    sampleHeight: 20
    boostType: GAB
    minHitRate: 0.995
    maxFalseAlarmRate: 0.5
    weightTrimRate: 0.95
    maxDepth: 1
    maxWeakCount: 100
    Number of unique features given windowSize [30,20] : 9135

    ===== TRAINING 0-stage =====
    Can not get new positive sample. The most possible reason is insufficient count of samples in given vec-file.
    > ) in CvCascadeImageReader::PosReader::get, file c:\build\master_winpack-build-win64-vc15\opencv\apps\traincascade\imagestorage.cpp, line 158

    1. Mình không biết bước 1 (tạo sample) của bạn thành công không, tuy nhiên thấy số lượng ảnh của bạn quá ít, tốt nhất từ 300 trở lên

  3. > opencv_createsamples -info E:\GreenParking\location.txt -vec GreenParking.vec -w 30 -h 20 -num 3500
    em chạy câu lệnh trên nhưng bị lỗi ở tham số -num 3500, báo lỗi như sau:
    >OpenCV(3.4.5) Error: Bad argument (> Can not get new positive sample. The most possible reason is insufficient count >of samples in given vec-file.
    em chỉnh sửa -num thành <= 1749 (số file ảnh dương thực tế) thì chạy được, em nghĩ giá trị tham số 3500 hình như có vấn đề phải không anh?

    1. oh thanks bạn đã chỉ ra sai sót, để mình cập nhật lại

  4. Em bị lỗi như thế này thì sửa như thế nào ạ???

    C:\opencv\build\x64\vc15\bin>opencv_traincascade -data D:\train -vec D:\GreenParking.vec -bg D:\negatives\bg.txt -numPos 1748 -numNeg 3000 -w 30 -h 20 -featureType LBP -mode ALL
    ———————————————————————————
    Training parameters are pre-loaded from the parameter file in data folder!
    Please empty this folder if you want to use a NEW set of training parameters.
    ———————————————————————————
    PARAMETERS:
    cascadeDirName: D:\train
    vecFileName: D:\GreenParking.vec
    bgFileName: D:\negatives\bg.txt
    numPos: 1748
    numNeg: 3000
    numStages: 20
    precalcValBufSize[Mb] : 1024
    precalcIdxBufSize[Mb] : 1024
    acceptanceRatioBreakValue : -1
    stageType: BOOST
    featureType: LBP
    sampleWidth: 30
    sampleHeight: 20
    boostType: GAB
    minHitRate: 0.995
    maxFalseAlarmRate: 0.5
    weightTrimRate: 0.95
    maxDepth: 1
    maxWeakCount: 100
    Number of unique features given windowSize [30,20] : 9135

    Stage 0 is loaded

    ===== TRAINING 1-stage =====
    Can not get new positive sample. The most possible reason is insufficient count of samples in given vec-file.
    > ) in CvCascadeImageReader::PosReader::get, file c:\build\3_4_winpack-build-win64-vc15\opencv\apps\traincascade\imagestorage.cpp, line 158

    1. lỗi này do app không thấy ảnh negatives. bạn vào folder negative double click vào file .bat để tạo file bg.txt mới

    2. mình đã làm theo bạn nhiều lần nhưng vẫn gặp lỗi này.

  5. anh ơi em bị lỗi như thế này thì sửa như thế nào ạ???
    C:\Users\Admin>C:\Users\Admin\Downloads\Programs\opencv\build\x64\vc12\bin\opencv_traincascade.exe
    Usage: C:\Users\Admin\Downloads\Programs\opencv\build\x64\vc12\bin\opencv_traincascade.exe
    -data
    -vec
    -bg
    [-numPos ]
    [-numNeg ]
    [-numStages ]
    [-precalcValBufSize ]
    [-precalcIdxBufSize ]
    [-baseFormatSave]
    –cascadeParams–
    [-stageType ]
    [-featureType ]
    [-w ]
    [-h ]
    –boostParams–
    [-bt ]
    [-minHitRate = 0.995>]
    [-maxFalseAlarmRate ]
    [-weightTrimRate ]
    [-maxDepth ]
    [-maxWeakCount ]
    –haarFeatureParams–
    [-mode C:\Users\Admin\Downloads\Programs\opencv\build\x64\vc12\bin\opencv_traincascade.exe-data D:\output -vec D:\bienso.vec -bg C:\Users\Admin\Desktop\anhsai\list.txt -numPos 15 -numNeg 13 -numStage 20 -minHitRate 0.995 -maxFalseAlarmRate 0.5 -w 134 -h 118
    ‘C:\Users\Admin\Downloads\Programs\opencv\build\x64\vc12\bin\opencv_traincascade.exe-data’ is not recognized as an internal or external command,
    operable program or batch file.

    1. opencv_traincascade.exe-data dính nhau nên không chạy được, bạn thêm khoảng trắng phía sau exe

    2. e cảm ơn anh!e sử được lỗi đó rồi ạ.nhưng giờ e bị lỗi này thì sử như nào ạ??
      C:\Users\Admin>C:\Users\Admin\Desktop\OPENCV\caidatopencv\build\x64\vc12\bin\opencv_traincascade.exe -data D:\train -vec bienso.vec -bg C:\Users\Admin\Desktop\ML\anhsai\list.txt -numPos 15 -numNeg 13 -w 135 -h 120 -featureType LBP -mode ALL
      Training parameters are loaded from the parameter file in data folder!
      Please empty the data folder if you want to use your own set of parameters.
      PARAMETERS:
      cascadeDirName: D:\train
      vecFileName: bienso.vec
      bgFileName: C:\Users\Admin\Desktop\ML\anhsai\list.txt
      numPos: 15
      numNeg: 13
      numStages: 20
      precalcValBufSize[Mb] : 256
      precalcIdxBufSize[Mb] : 256
      stageType: BOOST
      featureType: LBP
      sampleWidth: 135
      sampleHeight: 120
      boostType: GAB
      minHitRate: 0.995
      maxFalseAlarmRate: 0.5
      weightTrimRate: 0.95
      maxDepth: 1
      maxWeakCount: 100

      ===== TRAINING 0-stage =====

      Parameters can not be written, because file D:\train/params.xml can not be opened.

  6. Cho em hỏi tại sao chọn “-featureType LBP” mà lại có thêm “-mode ALL” ạ?
    Lệnh -mode em đọc trên trang OpenCV thì nó ghi là lệnh chọn kiểu cho HAAR
    Em cảm ơn!

    1. Đúng là mình nhầm thật, trong quá trình copy dư không hay

    2. à anh cho e hỏi thêm là cái lbpcascade_face_viscom.xml anh đã train = dataset gì và nó có hiệu quả hơn những cái đã có sẵn ko ạ?

    3. Mình train bằng ảnh thực tế của các bãi xe ở Sài Gòn, và nó rất hiệu quả khi sử dụng cho các bãi xe đó 😀 Còn với các bãi xe mới thì mình phải khảo sát, thu thập thêm ảnh rồi train lại

  7. chào anh hiện e đang muốn train cascade để nhận diện 1 chiếc lá trong ảnh, không biết là anh đã làm thử chưa có thể cho em xin data hoặc xml hoặc lời khuyên ạ?

    1. hi bạn, để train thì bạn làm đủ các bước: thu thập ảnh lá, traning đủ các bước là có thể sử dụng được, nếu lỗi ở bước nào thì chụp hình lại mình sẽ hướng dẫn tiếp

    2. vâng xin được hỏi 1 số cái ạ:
      – bộ data leaf e down trên mạng về trong ảnh chỉ có mỗi chiếc lá thì có cần dùng tool khoanh ko hay có cách nào khác để chọn cả ảnh luôn ạ
      – cái objectLocator trước giờ e vẫn dùng OK nhưng tự nhiên bây h bị lỗi Unhandled exception has occurred…

    3. – Bạn có thể viết 1 script nhỏ loop qua các file ảnh để tạo ra file location.txt chứa tên ảnh, 1 đối tượng, x=0, y=0, còn width và height là kích cỡ của từng ảnh
      – Bạn xem lại đường dẫn folder có chứa ký tự Unicode không?

    4. e thấy trong phần 3 có nói là ảnh dương nên có bg khác nhau nhưng bộ data down về có khoảng 2000 ảnh lá trên nền trắng thì có nên dùng ko ạ?

    5. Dùng bình thường bạn nhé, ảnh background nghĩa là ảnh không có đối tượng (negative) chứ không phải nền của ảnh dương nhé

    6. e gặp lỗi này là sao hả anh?
      OpenCV Error: Assertion failed (_img.cols == winSize.width) in CvCascadeImageReader::NegReader::get, file C:\builds\2_4_PackSlave-win64-vc12-shared\opencv\apps\traincascade\imagestorage.cpp, line 92

    7. Có thể là ảnh quá lớn, bạn kiểm tra lại các ảnh xem có ảnh nào chưa resize không

    8. vâng e train theo lệnh này thì ko được anh ạ, độ chính xác quá thấp luôn
      opencv_traincascade -data E:\Leaf -vec Leaf.vec -bg D:\test\negatives\negatives\bg.txt -numPos 1700 -numNeg 3000 -w 30 -h 20 -minHitRate 0.999999 -featureType LBP

    9. đúng rồi, có 1700 ảnh thôi mà, 4000-5000 ảnh mới đủ chính xác. Bài viết này chỉ giúp các bạn hiểu cách làm thôi

  8. đối với bài nhận dạng khẩu trang a mới đăng e có tham khảo nhưng thấy code khó quá e dốt ko hiểu được, e vẫn tiếp tục train cascade theo bài này vì e thấy nó dễ và kết quả nó cũng nhận rất tốt mặt đeo khẩu trang nhưng có 1 vấn đề là nó nhận luôn cả mặt ko đeo khẩu trang anh ạ. có cách nào khắc phục cái này để 1 phát ăn ngay = cascade được ko ạ?

    1. Nếu bạn muốn chỉ nhận ra khuôn mặt có đeo thì tất cả khuôn mặt không đeo khẩu trang bạn đưa vào ảnh negative nhé

    2. Bạn kiểm tra lại các điều sau nếu muốn chỉ detect mặt có đeo khẩu trang:
      1. Bộ ảnh dương không có khuôn mặt không đeo
      2. Bộ ảnh âm không có khuôn mặt đeo khẩu trang
      3. Bộ ảnh dữ liệu phải đủ nhiều (hơn 1000 ảnh)

      Nếu đã làm đúng 3 điều trên thì cứ thấy ảnh nào sai thì thu thập rồi cho học lại nhiều lần nó mới khôn được

    3. cám ơn a nhiều lắm, nhờ những lời khuyên của a mà e làm được rồi, tốc độ phát hiện cũng cao, e định bỏ nó vô làm 1 cái hệ thống nhắc nhở khi có người ko đeo KT, khi e bỏ 1 file mp3 vào để nhắc nhở thì có khi đeo KT rồi nhưng nó vẫn nhắc liên tục và phát cái file mp3 này nó làm chậm webcam, a cho e xin lời khuyên về cái này với

    4. Mình không nghĩ là file mp3 làm chậm đâu mà do code detect hơi chậm. Còn nếu bạn xác định chính xác nguyên nhân là do file mp3 (không play thì detect nhanh) thì làm như sau:
      – Nếu bạn sử dụng Python thì dùng lib pygame
      – Nếu bạn sử dụng ngôn ngữ khác thì chạy bất đồng bộ (thread/async) để tránh ảnh hưởng thread chính

    5. kiểu như khi nó phát file mp3 thì cái khung cam nó bị đơ lại ấy anh, để e thử pygame, nhân tiện thì a cho e hỏi a có bán rasberry pi ko ạ :D?

    6. vâng, a mua pi và các thiết bị như cam, loa, cảm biến nhiệt… ở đâu vậy ạ có thể chỉ e mua với :v

    7. hiện e muốn làm 1 con raspberry pi để nhận diện khuôn mặt, đo thân nhiệt và phát ra lời cảnh báo nhưng e ko rành nên ko biết phải mua những thiết bị nào, nhờ a tư vấn giúp e để được mô hình có giá rẻ mà hoạt động ổn ạ

    8. Phát hiện khuôn mặt hay nhận diện? Nếu chỉ phát hiện thì dùng Pi3 hay Pi4 đều được.

      Còn do thân nhiệt thì thiết bị xài tốt cũng khoảng 10tr trở lên nhé, rẻ hơn nó trả kết quả sai bét à.

    9. phát hiện a, e kiếm module rẻ đo chơi học thuật thôi à :D, nào h chưa biết tới mấy này nên mua nghiên cứu

Leave a Reply