36 #include <visp3/core/vpPolygon.h>
37 #include <visp3/mbt/vpMbtDistanceKltPoints.h>
38 #include <visp3/me/vpMeTracker.h>
40 #if defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
42 #if defined(VISP_HAVE_CLIPPER)
43 #include <clipper.hpp>
46 #if defined(__APPLE__) && defined(__MACH__)
47 #include <TargetConditionals.h>
55 vpMbtDistanceKltPoints::vpMbtDistanceKltPoints()
56 : H(), N(), N_cur(), invd0(1.), cRc0_0n(), initPoints(std::map<int,
vpImagePoint>()),
57 curPoints(std::map<int,
vpImagePoint>()), curPointsInd(std::map<int, int>()), nbPointsCur(0), nbPointsInit(0),
58 minNbPoint(4), enoughPoints(false), dt(1.), d0(1.), cam(), isTrackedKltPoints(true), polygon(nullptr),
59 hiddenface(nullptr), useScanLine(false)
66 vpMbtDistanceKltPoints::~vpMbtDistanceKltPoints() { }
82 initPoints = std::map<int, vpImagePoint>();
83 curPoints = std::map<int, vpImagePoint>();
84 curPointsInd = std::map<int, int>();
85 std::vector<vpImagePoint> roi;
86 polygon->getRoiClipped(cam, roi);
88 for (
unsigned int i = 0; i < static_cast<unsigned int>(_tracker.
getNbFeatures()); i++) {
98 if ((
unsigned int)y_tmp < hiddenface->getMbScanLineRenderer().getPrimitiveIDs().getHeight() &&
99 (
unsigned int)x_tmp < hiddenface->getMbScanLineRenderer().getPrimitiveIDs().getWidth() &&
100 hiddenface->getMbScanLineRenderer().getPrimitiveIDs()[(
unsigned int)y_tmp][(
unsigned int)x_tmp] ==
110 #ifdef TARGET_OS_IPHONE
113 curPointsInd[(int)
id] = (
int)i;
117 curPointsInd[id] = (int)i;
122 nbPointsInit = (
unsigned int)initPoints.size();
123 nbPointsCur = (
unsigned int)curPoints.size();
125 if (nbPointsCur >= minNbPoint)
128 enoughPoints =
false;
131 vpPlane plan(polygon->getPoint(0), polygon->getPoint(1), polygon->getPoint(2));
134 N = plan.getNormal();
151 unsigned int vpMbtDistanceKltPoints::computeNbDetectedCurrent(
const vpKltOpencv &_tracker,
const vpImage<bool> *mask)
156 curPoints = std::map<int, vpImagePoint>();
157 curPointsInd = std::map<int, int>();
159 for (
unsigned int i = 0; i < static_cast<unsigned int>(_tracker.
getNbFeatures()); i++) {
162 #ifdef TARGET_OS_IPHONE
163 curPoints[(int)
id] =
vpImagePoint(
static_cast<double>(y),
static_cast<double>(x));
164 curPointsInd[(int)
id] = (
int)i;
166 curPoints[id] =
vpImagePoint(
static_cast<double>(y),
static_cast<double>(x));
167 curPointsInd[id] = (int)i;
172 nbPointsCur = (
unsigned int)curPoints.size();
174 if (nbPointsCur >= minNbPoint)
177 enoughPoints =
false;
192 void vpMbtDistanceKltPoints::computeInteractionMatrixAndResidu(
vpColVector &_R,
vpMatrix &_J)
194 unsigned int index_ = 0;
196 std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
197 for (; iter != curPoints.end(); ++iter) {
199 double i_cur(iter->second.get_i()), j_cur(iter->second.get_j());
201 double x_cur(0), y_cur(0);
210 computeP_mu_t(x0, y0, x0_transform, y0_transform, H);
212 double invZ = compute_1_over_Z(x_cur, y_cur);
214 _J[2 * index_][0] = -invZ;
215 _J[2 * index_][1] = 0;
216 _J[2 * index_][2] = x_cur * invZ;
217 _J[2 * index_][3] = x_cur * y_cur;
218 _J[2 * index_][4] = -(1 + x_cur * x_cur);
219 _J[2 * index_][5] = y_cur;
221 _J[2 * index_ + 1][0] = 0;
222 _J[2 * index_ + 1][1] = -invZ;
223 _J[2 * index_ + 1][2] = y_cur * invZ;
224 _J[2 * index_ + 1][3] = (1 + y_cur * y_cur);
225 _J[2 * index_ + 1][4] = -y_cur * x_cur;
226 _J[2 * index_ + 1][5] = -x_cur;
228 _R[2 * index_] = (x0_transform - x_cur);
229 _R[2 * index_ + 1] = (y0_transform - y_cur);
234 double vpMbtDistanceKltPoints::compute_1_over_Z(
double x,
double y)
236 double num = cRc0_0n[0] * x + cRc0_0n[1] * y + cRc0_0n[2];
237 double den = -(d0 - dt);
253 inline void vpMbtDistanceKltPoints::computeP_mu_t(
double x_in,
double y_in,
double &x_out,
double &y_out,
256 double p_mu_t_2 = x_in * _cHc0[2][0] + y_in * _cHc0[2][1] + _cHc0[2][2];
258 if (fabs(p_mu_t_2) < std::numeric_limits<double>::epsilon()) {
264 x_out = (x_in * _cHc0[0][0] + y_in * _cHc0[0][1] + _cHc0[0][2]) / p_mu_t_2;
265 y_out = (x_in * _cHc0[1][0] + y_in * _cHc0[1][1] + _cHc0[1][2]) / p_mu_t_2;
291 vpGEMM(ctransc0, N, -invd0, cRc0, 1.0, cHc0, VP_GEMM_B_T);
314 for (
unsigned int i = 0; i < 3; i += 1) {
315 dt += ctransc0[i] * (N_cur[i]);
326 bool vpMbtDistanceKltPoints::isTrackedFeature(
int _id)
336 std::map<int, vpImagePoint>::iterator iter = initPoints.find(_id);
337 if (iter != initPoints.end())
352 void vpMbtDistanceKltPoints::updateMask(
354 unsigned char nb,
unsigned int shiftBorder)
356 int width = mask.cols;
357 int height = mask.rows;
359 int i_min, i_max, j_min, j_max;
360 std::vector<vpImagePoint> roi;
361 polygon->getRoiClipped(cam, roi);
363 double shiftBorder_d = (double)shiftBorder;
365 #if defined(VISP_HAVE_CLIPPER)
366 std::vector<vpImagePoint> roi_offset;
368 ClipperLib::Path path;
369 for (std::vector<vpImagePoint>::const_iterator it = roi.begin(); it != roi.end(); ++it) {
370 path.push_back(ClipperLib::IntPoint((ClipperLib::cInt)it->get_u(), (ClipperLib::cInt)it->get_v()));
373 ClipperLib::Paths solution;
374 ClipperLib::ClipperOffset co;
375 co.AddPath(path, ClipperLib::jtRound, ClipperLib::etClosedPolygon);
376 co.Execute(solution, -shiftBorder_d);
379 if (!solution.empty()) {
380 size_t index_max = 0;
382 if (solution.size() > 1) {
386 for (
size_t i = 0; i < solution.size(); i++) {
387 std::vector<vpImagePoint> corners;
389 for (
size_t j = 0; j < solution[i].size(); j++) {
390 corners.push_back(
vpImagePoint((
double)(solution[i][j].Y), (
double)(solution[i][j].X)));
394 if (polygon_area.
getArea() > max_area) {
395 max_area = polygon_area.
getArea();
401 for (
size_t i = 0; i < solution[index_max].size(); i++) {
402 roi_offset.push_back(
vpImagePoint((
double)(solution[index_max][i].Y), (
double)(solution[index_max][i].X)));
413 #if defined(VISP_HAVE_CLIPPER)
420 if (i_min > height) {
423 if (i_max > height) {
433 for (
int i = i_min; i < i_max; i++) {
434 double i_d = (double)i;
436 for (
int j = j_min; j < j_max; j++) {
437 double j_d = (double)j;
439 #if defined(VISP_HAVE_CLIPPER)
441 if (polygon_test.isInside(imPt)) {
442 mask.ptr<uchar>(i)[j] = nb;
445 if (shiftBorder != 0) {
450 mask.at<
unsigned char>(i, j) = nb;
455 mask.at<
unsigned char>(i, j) = nb;
471 void vpMbtDistanceKltPoints::removeOutliers(
const vpColVector &_w,
const double &threshold_outlier)
473 std::map<int, vpImagePoint> tmp;
474 std::map<int, int> tmp2;
475 unsigned int nbSupp = 0;
479 std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
480 for (; iter != curPoints.end(); ++iter) {
481 if (_w[k] > threshold_outlier && _w[k + 1] > threshold_outlier) {
483 tmp[iter->first] =
vpImagePoint(iter->second.get_i(), iter->second.get_j());
484 tmp2[iter->first] = curPointsInd[iter->first];
489 initPoints.erase(iter->first);
498 if (nbPointsCur >= minNbPoint)
501 enoughPoints =
false;
512 std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
513 for (; iter != curPoints.end(); ++iter) {
516 iP.
set_i(
static_cast<double>(iter->second.get_i()));
517 iP.
set_j(
static_cast<double>(iter->second.get_j()));
523 std::stringstream ss;
534 void vpMbtDistanceKltPoints::displayPrimitive(
const vpImage<vpRGBa> &_I)
536 std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
537 for (; iter != curPoints.end(); ++iter) {
540 iP.
set_i(
static_cast<double>(iter->second.get_i()));
541 iP.
set_j(
static_cast<double>(iter->second.get_j()));
547 std::stringstream ss;
555 bool displayFullModel)
557 std::vector<std::vector<double> > models = getModelForDisplay(camera, displayFullModel);
559 for (
size_t i = 0; i < models.size(); i++) {
569 bool displayFullModel)
571 std::vector<std::vector<double> > models = getModelForDisplay(camera, displayFullModel);
573 for (
size_t i = 0; i < models.size(); i++) {
586 std::vector<std::vector<double> > vpMbtDistanceKltPoints::getFeaturesForDisplay()
588 std::vector<std::vector<double> > features;
590 std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
591 for (; iter != curPoints.end(); ++iter) {
594 iP.
set_i(
static_cast<double>(iter->second.get_i()));
595 iP.
set_j(
static_cast<double>(iter->second.get_j()));
600 std::vector<double> params = { 1,
602 features.push_back(params);
616 std::vector<std::vector<double> > vpMbtDistanceKltPoints::getModelForDisplay(
const vpCameraParameters &camera,
617 bool displayFullModel)
619 std::vector<std::vector<double> > models;
621 if ((polygon->isVisible() && isTrackedKltPoints) || displayFullModel) {
622 std::vector<std::pair<vpPoint, unsigned int> > roi;
623 polygon->getPolygonClipped(roi);
625 for (
unsigned int j = 0; j < roi.size(); j += 1) {
634 std::vector<std::pair<vpPoint, vpPoint> > linesLst;
636 if (useScanLine && !displayFullModel)
637 hiddenface->computeScanLineQuery(roi[j].first, roi[(j + 1) % roi.size()].first, linesLst,
true);
639 linesLst.push_back(std::make_pair(roi[j].first, roi[(j + 1) % roi.size()].first));
641 for (
unsigned int i = 0; i < linesLst.size(); i++) {
642 linesLst[i].first.project();
643 linesLst[i].second.project();
646 std::vector<double> params = { 0,
648 models.push_back(params);
657 #elif !defined(VISP_BUILD_SHARED_LIBS)
660 void dummy_vpMbtDistanceKltPoints() { };
void vpGEMM(const vpArray2D< double > &A, const vpArray2D< double > &B, const double &alpha, const vpArray2D< double > &C, const double &beta, vpArray2D< double > &D, const unsigned int &ops=0)
Generic class defining intrinsic camera parameters.
Implementation of column vector and the associated operations.
Class to define RGB colors available for display functionalities.
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)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
@ divideByZeroError
Division by zero.
Implementation of an homogeneous matrix and operations on such kind of matrices.
void extract(vpRotationMatrix &R) const
Implementation of an homography and operations on homographies.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
void set_ij(double ii, double jj)
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
int getNbFeatures() const
Get the number of current features.
void getFeature(const int &index, long &id, float &x, float &y) const
static int round(double x)
Implementation of a matrix and operations on matrices.
static bool inRoiMask(const vpImage< bool > *mask, unsigned int i, unsigned int j)
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
This class defines the container for a plane geometrical structure.
static void getMinMaxRoi(const std::vector< vpImagePoint > &roi, int &i_min, int &i_max, int &j_min, int &j_max)
Defines a generic 2D polygon.
vpPolygon & buildFrom(const std::vector< vpImagePoint > &corners, const bool &create_convex_hull=false)
bool isInside(const vpImagePoint &iP, const PointInPolygonMethod &method=PnPolyRayCasting) const
Implementation of a rotation matrix and operations on such kind of matrices.
Class that consider the case of a translation vector.