Giống tôm thẻ chân chân trắng thương phẩm có màu sắc trong suốt, kích thước từ 10-20mm. Ở phần đầu tôm có chấm màu đen khá lớn so với thân (chiếm 1/3 diện tích). Dựa vào đặc trưng đó để đếm tôm giống tự động.
Các bước thực hiện
– Chuyển ảnh sang ảnh xám
– Lấy ngưỡng nghịch đảo để được ảnh nhị phân
– Dùng hàm distanceTransform() để tìm những blob lớn nhất
– Lấy các blob theo kích cỡ min-max mà người dùng chỉ định
– Xuất kết quả
Hàm distanceTransform() biến đổi ảnh với công thức: pixel nào càng gần background thì giá trị càng nhỏ, pixel nào càng xa background thì giá trị càng lớn.
Kết quả
Các vấn đề lưu ý
– Để tôm vào khay với số lượng vừa phải, ít nước để tôm đừng chồng lấn nhau.
– Để thiết bị chụp ảnh & khay ở vị trí cố định vì phải setup min-max size của tôm.
Code
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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
std::vector<std::vector<cv::Point>> ClampContourBySize(std::vector<std::vector<cv::Point>> contours, int minValue, int maxValue) { std::vector<std::vector<cv::Point>> result; for (int i = 0; i < contours.size(); ++i) { cv::Rect r = cv::boundingRect(contours[i]); float distance = abs(r.width - r.height) / (r.width + r.height); if (distance < 0.5) { if (minValue <= r.width &&r.width <= maxValue && minValue <= r.height && r.height <= maxValue) { result.push_back(contours[i]); } } } return result; } int ShrimpCounter(cv::Mat &matInput) { cv::Mat matGray = TGMTimage::ConvertToGray(matInput); cv::imshow("mat gray", matGray); //blur cv::Mat matBlur; cv::blur(matGray, matBlur, cv::Size(29, 29)); //threshold cv::Mat matBinary; cv::adaptiveThreshold(matBlur, matBinary, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 21, 0); cv::imshow("binary", matBinary); //Finding sure foreground area cv::Mat dist_transform; cv::distanceTransform(matBinary, dist_transform, CV_DIST_L2, 3); cv::Mat matNorm; cv::normalize(dist_transform, matNorm, 0, 1, cv::NORM_MINMAX); cv::imshow("matNorm", matNorm); double min, max; cv::minMaxLoc(dist_transform, &min, &max); cv::Mat sure_fg; cv::threshold(dist_transform, sure_fg, 0.4*max, 255, CV_THRESH_BINARY); cv::imshow("sure_fg", sure_fg); //convert to 1 channel sure_fg.convertTo(sure_fg, CV_8U); std::vector<std::vector<cv::Point>> contours; cv::findContours(sure_fg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); contours = ClampContourBySize(contours, m_minSize, m_maxSize); if (matInput.channels() == 1) { cv::cvtColor(matInput, matInput, CV_GRAY2BGR); } for (int i = 0; i < contours.size(); i++) { cv::RotatedRect rrect = cv::minAreaRect(contours[i]); cv::rectangle(matInput, rrect.boundingRect, GREEN, 1); } cv::imshow("Output", matInput); return contours.size(); } |
Chương trình không cung cấp min, max, thấy đoạn vẽ chữ nhật nhưng không thấy đoạn hiển thị số thứ tự và số lượng tôm. Có bác nào hiển thị được không?