Để tìm đối tượng trong ảnh thì có nhiều cách, nổi tiếng nhất là Haar Cascade, tuy nhiên lại tốn thời gian để train. (Chưa kể đến train bị fail khá nhiều) Tìm đối tượng bằng Template matching phù hợp với đối tượng đơn giản, ít thay đổi. Cách này cũng rất phù hợp để đếm vật thể giống nhau, như là đếm hàng hóa trên kệ.
Ví dụ đơn giản là tìm logo hoặc vật thể đã biết trong ảnh, hoặc là biển báo giao thông. Phần implement thì opencv đã thực hiện hoàn chỉnh, bài này chỉ giới thiệu cách ứng dụng vào đếm hàng hóa.
Một ví dụ khác về tìm vật thể 2D (không sử dụng template matching): Tìm đồng xu trong ảnh
So sánh với Haar cascade
Ưu điểm:
- Tốc độ tìm kiếm nhanh
- Không tốn thời gian training
- Cách sử dụng đơn giản
Nhược điểm:
- Không chứa được nhiều đặc trưng như Haar Cascade
Cách sử dụng
Template matching có tất cả 6 phương pháp để tìm, tuy nhiên qua thử nghiệm thì phương pháp CV_TM_CCORR_NORMED chính xác nhất. Các bạn nên kiểm tra lại vì có thể mình chưa thử đủ hết các trường hợp.
Để sử dụng ta cần có 3 tham số: ảnh cần tìm đối tượng, mẫu và phương pháp tìm. Bên dưới là ảnh về kệ hàng Coca-Cola và mẫu dùng để tìm. Các bạn dùng chính ảnh bên dưới để thử nghiệm code
Code c++
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 57 58 59 |
void main(int argc, char** argv) { //load ảnh cv::Mat matToFind = cv::imread("stock.jpg"); cv::Mat matTemplate = cv::imread("coca2.jpg"); //kiểm tra kích cỡ của ảnh input & template if (matTemplate.rows > matToFind.rows || matTemplate.cols > matToFind.cols) { std::cout<<("Mat template must be smaller than matInput"); return; } cv::Mat matDisplay, result; matToFind.copyTo(matDisplay); int result_cols = matToFind.cols - matTemplate.cols + 1; int result_rows = matToFind.rows - matTemplate.rows + 1; result.create(result_rows, result_cols, CV_32FC1); //tìm mẫu cv::matchTemplate(matToFind, matTemplate, result, CV_TM_CCORR_NORMED); cv::threshold(result, result, 0.9, 1., CV_THRESH_TOZERO); int count = 0; double minval, maxval; //ngưỡng chính xác, giảm xuống thì sẽ tìm được nhiều đối tượng hơn nhưng sai số nhiều hơn threshold = 0.9; while (true) { cv::Point minloc, maxloc; cv::minMaxLoc(result, &minval, &maxval, &minloc, &maxloc); if (maxval > threshold) { //vẽ hình chữ nhật lên đối tượng tìm được cv::rectangle( matToFind, maxloc, cv::Point(maxloc.x + matTemplate.cols, maxloc.y + matTemplate.rows), cv::Scalar(0, 255, 0), 2 ); cv::floodFill(result, maxloc, cv::Scalar(0), 0, cv::Scalar(.1), cv::Scalar(1.)); count++; } else break; } cv::imshow("detected", matToFind); cout << "Counted: " << count; cv::waitKey(); getchar(); } |
Kết quả
Tìm được 29 đối tượng (chai nước ngọt) trong ảnh
kiểm tra đối tượng chuyển động được ko ad
giả sử đối tượng cđộng dc capture bằng webcam :https://thigiacmaytinh.com/lay-hinh-anh-tu-webcam/ của ad viết sau đó sd template matching bắt lại r so sánh lúc các chai côca đang chuyển động. Chụp lại với tốc độ 24 ảnh/s
mình cần video quay thực tế mới trả lời được vì còn ảnh hưởng bởi chất lượng camera
camera 640×480 pixels là thoải mái ad ạ. Em sd webcam làm bài tập xử lý ảnh thấy hơi giật. Quan trọng ở videocaputure sử dụng lấy bao nhiêu frame/s ấy. với lúc nó thay đổi góc xoay của ảnh mẫu thì nó ko bắt dc nữa
Làm videocapture webcam thu hình liên tục 10 ảnh/s real time như ad khoai mà học thuật vãi
ad cho e hỏi là sử dụng hàm thư viện nào ạ?
anh ơi, cho em hỏi phương pháp này tìm cái hình có chữ coca cola chính diện như ảnh mẫu được không anh. Ví dụ này tìm ra 29 ảnh nhưng có vài ảnh cái chữ xoay hướng khác.
Mình cần điều chỉnh tham số gì ạ? Ý em là tìm hình giống 90-99% luôn ấy, áp dụng cho bài toán phát hiện lỗi, thường là lỗi giống mẫu 95%
Hi bạn, hiện nay cách này đã lỗi thời. Có nhiều mô hình mới hơn như YOLO sẽ giúp bạn được tìm được vị trí của vật thể và tìm tỉ lệ giống nhau chính xác hơn rất nhiều
Em muốn dùng pp này tìm hình giống trên 95% thì sp tốt, mà giống 94% báo sản phẩm lỗi