Я работаю над обнаружением объектов с помощью opencv.
Я хочу нарисовать прямоугольник вокруг объекта после нажатия на него мышью.
Какую технику я могу использовать? Я пытался с SURF, но тщетно.
Любая помощь будет оценена.
Какие изображения вы хотите использовать?
Если изображение является своего рода простым (например, карандаш на белой бумаге, отметка на простой стене), рассмотрите ли вы использование следующего подхода? Я думаю, что это очень классический подход, но хорошо работает, когда ситуация ограничена.
cv::Mat img = // your image.
double threshold = 128; // needs adjustment.
int n_erode_dilate = 1; // needs adjustment.
cv::Mat m = img.clone();
cv::cvtColor(m, m, CV_RGB2GRAY); // convert to glayscale image.
cv::blur(m, m, cv::Size(5,5));
cv::threshold(m, m, threshold, 255,CV_THRESH_BINARY_INV);
cv::erode(m, m, cv::Mat(),cv::Point(-1,-1),n_erode_dilate);
cv::dilate(m, m, cv::Mat(),cv::Point(-1,-1),n_erode_dilate);
std::vector< std::vector<cv::Point> > contours;
std::vector<cv::Point> points;
cv::findContours(m, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
for (size_t i=0; i<contours.size(); i++) {
for (size_t j = 0; j < contours[i].size(); j++) {
cv::Point p = contours[i][j];
points.push_back(p);
}
}
// And process the points or contours to pick up specified object.
// for example: draws rectangle on original image.
if(points.size() > 0){
cv::Rect brect = cv::boundingRect(cv::Mat(points).reshape(2));
cv::rectangle(img, brect.tl(), brect.br(), cv::Scalar(100, 100, 200), 2, CV_AA);
}
Прежде чем вы сможете найти ограничивающий прямоугольник, объект должен быть обнаружен. Нажав на объект, вы указываете только тот пиксель, который принадлежит объекту. Этого недостаточно, потому что вы ничего не знаете о форме объекта. Поэтому нажатие на объект не означает обнаружение объекта.
Как вы обнаружите объект, зависит от приложения. Один из способов найти контур объекта (ребра) — это сегментация. Заглянуть в водораздел или же grabcut алгоритмы сегментации в OpenCV. Это даст вам контур объекта (если объект выделяется на фоне). В общем, метод обнаружения объекта зависит от приложения, и это активная область исследований. Знание того, какой тип объекта обнаруживается, может значительно помочь в обнаружении и сегментации.
Как только у вас есть контур объекта, вы можете найти его ограничивающий прямоугольник, используя boundingRect функция. Рисовать прямоугольник легко, просто используйте прямоугольник функция.
Мой лучший совет — сначала обнаружить объект, используя некоторые методы обработки изображений OpenCV, такие как ….. Порог для двоичного изображения, используйте размытие для улучшения обнаружения краев, используйте хитрый фильтр, возможно, размывающий и растягивающий.
Как только вы получите приличный порог, в котором ваша ROI выделяется на фоне, я бы использовал функцию findcontours, чтобы получить контуры всех сгустков, присутствующих в вашем изображении, если вы получите несколько непривычных контуров, которые вы можете указать, чтобы рисовать контур, только если больше чем X.
Как только вы сохраните контуры области интереса (в векторе), следующим шагом будет нарисовать ограничивающие рамки вокруг этих контуров с помощью функции Rect.
OpenCV — это очень открытое поле для каждой проблемы, есть множество решений или путей, которые вы можете выбрать. Я очень рекомендую посетить Документация OpenCv
Но сначала проверьте версию OpenCV, которую вы установили или используете
Если объект довольно простой и одного цвета, вы можете попробовать использовать алгоритм водораздела https://code.ros.org/trac/opencv/browser/trunk/opencv/samples/cpp/watershed.cpp?rev=4270 Он должен хорошо работать для однотонных объектов, таких как карандаш, но определенно потерпит неудачу в более сложных ситуациях.
после cvtColor эрозии расширяются
// get the contours
std::vector< std::vector< cv::Point> > contours;
cv::findContours(imageMat, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
// http://blog.csdn.net/corcplusplusorjava/article/details/20536251
// draw contours
cv::drawContours(imageMat , allContours ,-1 , cv::Scalar(0) , 2) ;