34 #include <visp3/vision/vpPlanarObjectDetector.h>
36 #if (VISP_HAVE_OPENCV_VERSION >= 0x020408) && \
37 (VISP_HAVE_OPENCV_VERSION < 0x030000)
39 #include <visp3/core/vpColor.h>
40 #include <visp3/core/vpDisplay.h>
41 #include <visp3/core/vpException.h>
42 #include <visp3/core/vpImageConvert.h>
43 #include <visp3/core/vpImagePoint.h>
44 #include <visp3/core/vpImageTools.h>
54 vpPlanarObjectDetector::vpPlanarObjectDetector()
55 : fern(), homography(), H(), dst_corners(), isCorrect(false), ref_corners(), modelROI(), currentImagePoints(),
56 refImagePoints(), minNbMatching(10)
67 vpPlanarObjectDetector::vpPlanarObjectDetector(
const std::string &_dataFile,
const std::string &_objectName)
68 : fern(), homography(), H(), dst_corners(), isCorrect(false), ref_corners(), modelROI(), currentImagePoints(),
69 refImagePoints(), minNbMatching(10)
71 load(_dataFile, _objectName);
77 void vpPlanarObjectDetector::init() { }
84 vpPlanarObjectDetector::~vpPlanarObjectDetector() { }
93 void vpPlanarObjectDetector::computeRoi(
vpImagePoint *ip,
unsigned int nbpt)
99 std::vector<vpImagePoint> ptsx(nbpt);
100 std::vector<vpImagePoint> ptsy(nbpt);
101 for (
unsigned int i = 0; i < nbpt; i++) {
102 ptsx[i] = ptsy[i] = ip[i];
105 for (
unsigned int i = 0; i < nbpt; i++) {
106 for (
unsigned int j = 0; j < nbpt - 1; j++) {
107 if (ptsx[j].get_j() > ptsx[j + 1].get_j()) {
108 double tmp = ptsx[j + 1].
get_j();
109 ptsx[j + 1].set_j(ptsx[j].get_j());
114 for (
unsigned int i = 0; i < nbpt; i++) {
115 for (
unsigned int j = 0; j < nbpt - 1; j++) {
116 if (ptsy[j].get_i() > ptsy[j + 1].get_i()) {
117 double tmp = ptsy[j + 1].get_i();
118 ptsy[j + 1].set_i(ptsy[j].get_i());
139 modelROI.width = (int)_I.
getWidth();
142 initialiseRefCorners(modelROI);
144 return fern.buildReference(_I);
161 unsigned int _height,
unsigned int _width)
163 unsigned int res = fern.buildReference(_I, _iP, _height, _width);
164 modelROI.x = (int)_iP.
get_u();
165 modelROI.y = (int)_iP.
get_v();
166 modelROI.width = (int)_width;
167 modelROI.height = (int)_height;
169 initialiseRefCorners(modelROI);
186 unsigned int res = fern.buildReference(_I, _rectangle);
190 modelROI.x = (int)iP.
get_u();
191 modelROI.y = (int)iP.
get_v();
192 modelROI.width = (int)_rectangle.
getWidth();
193 modelROI.height = (int)_rectangle.
getHeight();
195 initialiseRefCorners(modelROI);
215 std::vector<cv::Point2f> refPts = fern.getRefPt();
216 std::vector<cv::Point2f> curPts = fern.getCurPt();
218 for (
unsigned int i = 0; i < refPts.size(); ++i) {
219 refPts[i].x += modelROI.x;
220 refPts[i].y += modelROI.y;
222 for (
unsigned int i = 0; i < curPts.size(); ++i) {
223 curPts[i].x += modelROI.x;
224 curPts[i].y += modelROI.y;
227 if (curPts.size() < 4) {
228 for (
unsigned int i = 0; i < 3; i += 1) {
229 for (
unsigned int j = 0; j < 3; j += 1) {
231 homography[i][j] = 1;
234 homography[i][j] = 0;
242 std::vector<unsigned char> mask;
243 H = cv::findHomography(cv::Mat(refPts), cv::Mat(curPts), mask, cv::RANSAC, 10);
246 const cv::Mat_<double> &H_tmp = H;
247 dst_corners.resize(4);
248 for (
unsigned int i = 0; i < 4; i++) {
249 cv::Point2f pt = ref_corners[i];
251 double w = 1. / (H_tmp(2, 0) * pt.x + H_tmp(2, 1) * pt.y + H_tmp(2, 2));
252 dst_corners[i] = cv::Point2f((
float)((H_tmp(0, 0) * pt.x + H_tmp(0, 1) * pt.y + H_tmp(0, 2)) * w),
253 (
float)((H_tmp(1, 0) * pt.x + H_tmp(1, 1) * pt.y + H_tmp(1, 2)) * w));
256 double *ptr = (
double *)H_tmp.data;
257 for (
unsigned int i = 0; i < 9; i++) {
258 this->homography[(
unsigned int)(i / 3)][i % 3] = *(ptr++);
266 currentImagePoints.resize(0);
267 refImagePoints.resize(0);
268 for (
unsigned int i = 0; i < mask.size(); i += 1) {
271 ip.
set_i(curPts[i].y);
272 ip.
set_j(curPts[i].x);
273 currentImagePoints.push_back(ip);
274 ip.
set_i(refPts[i].y);
275 ip.
set_j(refPts[i].x);
276 refImagePoints.push_back(ip);
280 if (currentImagePoints.size() < minNbMatching) {
304 vpTRACE(
"Bad size for the subimage");
312 return this->matchPoint(subImage);
331 return (this->matchPoint(I, iP, (
unsigned int)rectangle.
getHeight(), (
unsigned int)rectangle.
getWidth()));
346 for (
unsigned int i = 0; i < dst_corners.size(); i++) {
347 vpImagePoint ip1(dst_corners[i].y - modelROI.y, dst_corners[i].x - modelROI.x);
348 vpImagePoint ip2(dst_corners[(i + 1) % dst_corners.size()].y - modelROI.y,
349 dst_corners[(i + 1) % dst_corners.size()].x - modelROI.x);
354 for (
unsigned int i = 0; i < currentImagePoints.size(); ++i) {
355 vpImagePoint ip(currentImagePoints[i].get_i() - modelROI.y, currentImagePoints[i].get_j() - modelROI.x);
380 display(Icurrent, displayKpts);
383 for (
unsigned int i = 0; i < refImagePoints.size(); ++i) {
399 void vpPlanarObjectDetector::load(
const std::string &dataFilename,
const std::string &objName)
401 fern.load(dataFilename, objName);
402 modelROI = fern.getModelROI();
403 initialiseRefCorners(modelROI);
413 void vpPlanarObjectDetector::recordDetector(
const std::string &objectName,
const std::string &dataFile)
415 fern.record(objectName, dataFile);
423 std::vector<vpImagePoint> vpPlanarObjectDetector::getDetectedCorners()
const
426 std::vector<vpImagePoint> corners;
428 for (
unsigned int i = 0; i < dst_corners.size(); i++) {
429 ip.
set_uv(dst_corners[i].x, dst_corners[i].y);
430 corners.push_back(ip);
441 void vpPlanarObjectDetector::initialiseRefCorners(
const cv::Rect &_modelROI)
445 ip.y = (float)_modelROI.y;
446 ip.x = (
float)_modelROI.x;
447 ref_corners.push_back(ip);
449 ip.y = (float)(_modelROI.y + _modelROI.height);
450 ip.x = (float)_modelROI.x;
451 ref_corners.push_back(ip);
453 ip.y = (float)(_modelROI.y + _modelROI.height);
454 ip.x = (float)(_modelROI.x + _modelROI.width);
455 ref_corners.push_back(ip);
457 ip.y = (float)_modelROI.y;
458 ip.x = (
float)(_modelROI.x + _modelROI.width);
459 ref_corners.push_back(ip);
462 void vpPlanarObjectDetector::getReferencePoint(
unsigned int _i,
vpImagePoint &_imPoint)
464 if (_i >= refImagePoints.size()) {
467 _imPoint = refImagePoints[_i];
470 void vpPlanarObjectDetector::getMatchedPoints(
const unsigned int _index,
vpImagePoint &_referencePoint,
474 if (_index >= currentImagePoints.size()) {
478 _referencePoint = refImagePoints[_index];
479 _currentPoint = currentImagePoints[_index];
482 #elif !defined(VISP_BUILD_SHARED_LIBS)
485 void dummy_vpPlanarObjectDetector() { };
static const vpColor green
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
error that can be emitted by ViSP classes.
@ badValue
Used to indicate that a value is not in the allowed range.
@ notInTheImage
Pixel not in the image.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
void set_uv(double u, double v)
unsigned int getWidth() const
unsigned int getHeight() const
Defines a rectangle in the plane.
vpImagePoint getTopLeft() const