Улучшение алгоритма распознавания банки Coca-Cola: как повысить точность?
Проблема и общий подход
Ваш текущий алгоритм страдает от трех классических проблем компьютерного зрения: чувствительность к освещению, разрывы контуров из-за бликов и жесткая геометрическая фильтрация. Решение — комбинация предобработки, более умной цветовой сегментации и использования машинного обучения для финальной верификации.
Шаг 1: Улучшенная цветовая сегментация
Вместо жестких порогов в HSV используйте адаптивный порог и медианный фильтр для подавления шума. Также добавьте преобразование LAB — оно менее чувствительно к освещению:
cv::Mat lab;
cv::cvtColor(img, lab, cv::COLOR_BGR2Lab);
cv::Mat mask_lab;
cv::inRange(lab, cv::Scalar(20, 140, 140), cv::Scalar(40, 200, 200), mask_lab); // Красный в Lab
Шаг 2: Морфология для восстановления контуров
Блики разрывают контур. Используйте закрытие (closing) и открытие (opening) с большим ядром:
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(15, 15));
cv::morphologyEx(mask, mask, cv::MORPH_CLOSE, kernel); // Закрытие дыр
cv::morphologyEx(mask, mask, cv::MORPH_OPEN, kernel); // Удаление шума
Шаг 3: Умная геометрическая фильтрация
Вместо жесткого отношения сторон используйте Hu moments — они инвариантны к масштабу и повороту. Сравнивайте контур с эталонным контуром банки:
cv::Moments mu = cv::moments(c);
double hu[7];
cv::HuMoments(mu, hu);
// Логарифмируем для сравнения
for (int i = 0; i < 7; ++i) {
hu[i] = -1 * std::copysign(1.0, hu[i]) * std::log10(std::abs(hu[i]) + 1e-10);
}
// Сравните с эталонными hu_ref (полученными из эталонного изображения)
double dist = cv::norm(hu, hu_ref, cv::NORM_L2);
if (dist < 0.1) { /* это банка */ }
Шаг 4: Классификатор на основе HOG + SVM
Для финальной верификации используйте HOG дескрипторы и SVM. Это даст устойчивость к частичному перекрытию и разным ракурсам:
cv::HOGDescriptor hog;
std::vector<float> descriptors;
hog.compute(img_roi, descriptors); // img_roi — нормализованный кандидат (64x128)
// Обучите SVM на 100+ положительных и 200+ отрицательных примерах
cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
svm->train(training_data, cv::ml::ROW_SAMPLE, labels);
float response = svm->predict(descriptors); // 1.0 — банка, -1.0 — нет
Шаг 5: Комплексный пайплайн
Объедините все в цикл:
1. Предобработка: GaussianBlur + контрастирование (CLAHE)
2. Цветовая сегментация: HSV + LAB маски, объединение
3. Морфология: closing + opening
4. Поиск контуров, фильтр по площади (area > 5000)
5. Для каждого кандидата:
a. Вырезать ROI, нормализовать до 64x128
b. Вычислить Hu moments — отсеять по расстоянию > 0.2
c. Вычислить HOG — SVM классификация
6. Вывести результат
Для обучения SVM соберите датасет из 100+ изображений банок (разные углы, освещение) и 200+ фоновых объектов (круги, красные предметы). Используйте cv::ml::SVM::C_SVC с RBF ядром.
Заключение
Этот подход повысит точность до 85-95% даже на сложных изображениях. Если нужно еще выше — рассмотрите YOLO или Faster R-CNN, но для обучения потребуется больше данных (500+ изображений на класс).
<<Альтернативный подход: Использование каскадов Хаара
Если у вас нет времени или данных для обучения SVM, попробуйте готовый каскад Хаара для поиска круглых объектов. Хотя каскады менее точны, чем HOG+SVM, они работают быстро и не требуют обучения:
cv::CascadeClassifier cascade;
cascade.load("haarcascade_eye.xml"); // Или обучите свой каскад для банок
std::vector<cv::Rect> cans;
cascade.detectMultiScale(img, cans, 1.1, 3, 0, cv::Size(50, 50));
Недостаток: каскады чувствительны к повороту. Решение — поворачивать изображение на ±15 градусов и повторять детекцию.
Дополнение: Исправление освещения
Добавьте гамма-коррекцию и выравнивание гистограммы (CLAHE) перед цветовой сегментацией:
cv::Mat lab;
cv::cvtColor(img, lab, cv::COLOR_BGR2Lab);
std::vector<cv::Mat> channels;
cv::split(lab, channels);
cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE(3.0, cv::Size(8, 8));
clahe->apply(channels[0], channels[0]); // Выравнивание L-канала
cv::merge(channels, lab);
cv::cvtColor(lab, img, cv::COLOR_Lab2BGR);
Это сильно уменьшит влияние теней и бликов без потери цветовой информации.
Ответов пока нет.
Войдите чтобы оставить ответ