36 #include <visp3/core/vpPolygon.h>
37 #include <visp3/mbt/vpMbtDistanceKltCylinder.h>
38 #include <visp3/mbt/vpMbtDistanceKltPoints.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 vpMbtDistanceKltCylinder::vpMbtDistanceKltCylinder()
56 : c0Mo(), p1Ext(), p2Ext(), cylinder(), circle1(), circle2(), initPoints(), initPoints3D(), curPoints(),
57 curPointsInd(), nbPointsCur(0), nbPointsInit(0), minNbPoint(4), enoughPoints(false), cam(),
58 isTrackedKltCylinder(true), listIndicesCylinderBBox(), hiddenface(nullptr), useScanLine(false)
65 vpMbtDistanceKltCylinder::~vpMbtDistanceKltCylinder() { }
67 void vpMbtDistanceKltCylinder::buildFrom(
const vpPoint &p1,
const vpPoint &p2,
const double &r)
87 circle1.setWorldCoordinates(ABC[0], ABC[1], ABC[2], p1.
get_oX(), p1.
get_oY(), p1.
get_oZ(), r);
88 circle2.setWorldCoordinates(ABC[0], ABC[1], ABC[2], p2.
get_oX(), p2.
get_oY(), p2.
get_oZ(), r);
91 cylinder.setWorldCoordinates(ABC[0], ABC[1], ABC[2], (p1.
get_oX() + p2.
get_oX()) / 2.0,
106 cylinder.changeFrame(cMo);
111 initPoints = std::map<int, vpImagePoint>();
112 initPoints3D = std::map<int, vpPoint>();
113 curPoints = std::map<int, vpImagePoint>();
114 curPointsInd = std::map<int, int>();
116 for (
unsigned int i = 0; i < static_cast<unsigned int>(_tracker.
getNbFeatures()); i++) {
119 _tracker.
getFeature((
int)i, id, x_tmp, y_tmp);
124 if ((
unsigned int)y_tmp < hiddenface->getMbScanLineRenderer().getPrimitiveIDs().getHeight() &&
125 (
unsigned int)x_tmp < hiddenface->getMbScanLineRenderer().getPrimitiveIDs().getWidth()) {
126 for (
unsigned int kc = 0; kc < listIndicesCylinderBBox.size(); kc++)
127 if (hiddenface->getMbScanLineRenderer().getPrimitiveIDs()[(
unsigned int)y_tmp][(
unsigned int)x_tmp] ==
128 listIndicesCylinderBBox[kc]) {
135 std::vector<vpImagePoint> roi;
136 for (
unsigned int kc = 0; kc < listIndicesCylinderBBox.size(); kc++) {
137 hiddenface->getPolygon()[(size_t)listIndicesCylinderBBox[kc]]->getRoiClipped(cam, roi);
148 double xm = 0, ym = 0;
150 double Z = computeZ(xm, ym);
152 #ifdef TARGET_OS_IPHONE
155 curPointsInd[(int)
id] = (
int)i;
159 curPointsInd[id] = (int)i;
166 #ifdef TARGET_OS_IPHONE
167 initPoints3D[(int)
id] = p;
169 initPoints3D[id] = p;
177 if (nbPointsCur >= minNbPoint)
180 enoughPoints =
false;
194 unsigned int vpMbtDistanceKltCylinder::computeNbDetectedCurrent(
const vpKltOpencv &_tracker)
199 curPoints = std::map<int, vpImagePoint>();
200 curPointsInd = std::map<int, int>();
202 for (
unsigned int i = 0; i < static_cast<unsigned int>(_tracker.
getNbFeatures()); i++) {
204 if (isTrackedFeature((
int)
id)) {
205 #ifdef TARGET_OS_IPHONE
206 curPoints[(int)
id] =
vpImagePoint(
static_cast<double>(y),
static_cast<double>(x));
207 curPointsInd[(int)
id] = (
int)i;
209 curPoints[id] =
vpImagePoint(
static_cast<double>(y),
static_cast<double>(x));
210 curPointsInd[id] = (int)i;
216 if (nbPointsCur >= minNbPoint)
219 enoughPoints =
false;
232 void vpMbtDistanceKltCylinder::removeOutliers(
const vpColVector &_w,
const double &threshold_outlier)
234 std::map<int, vpImagePoint> tmp;
235 std::map<int, int> tmp2;
236 unsigned int nbSupp = 0;
240 std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
241 for (; iter != curPoints.end(); ++iter) {
242 if (_w[k] > threshold_outlier && _w[k + 1] > threshold_outlier) {
244 tmp[iter->first] =
vpImagePoint(iter->second.get_i(), iter->second.get_j());
245 tmp2[iter->first] = curPointsInd[iter->first];
250 initPoints.erase(iter->first);
257 curPoints = std::map<int, vpImagePoint>();
258 curPointsInd = std::map<int, int>();
262 if (nbPointsCur >= minNbPoint)
265 enoughPoints =
false;
283 unsigned int index_ = 0;
285 cylinder.changeFrame(_cMc0 * c0Mo);
287 std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
288 for (; iter != curPoints.end(); ++iter) {
290 double i_cur(iter->second.get_i()), j_cur(iter->second.get_j());
292 double x_cur(0), y_cur(0);
299 double x0_transform(p0.
get_x()), y0_transform(p0.
get_y());
301 double Z = computeZ(x_cur, y_cur);
303 if (
vpMath::isNaN(Z) || Z < std::numeric_limits<double>::epsilon()) {
309 _J[2 * index_][0] = 0;
310 _J[2 * index_][1] = 0;
311 _J[2 * index_][2] = 0;
312 _J[2 * index_][3] = 0;
313 _J[2 * index_][4] = 0;
314 _J[2 * index_][5] = 0;
316 _J[2 * index_ + 1][0] = 0;
317 _J[2 * index_ + 1][1] = 0;
318 _J[2 * index_ + 1][2] = 0;
319 _J[2 * index_ + 1][3] = 0;
320 _J[2 * index_ + 1][4] = 0;
321 _J[2 * index_ + 1][5] = 0;
323 _R[2 * index_] = (x0_transform - x_cur);
324 _R[2 * index_ + 1] = (y0_transform - y_cur);
328 double invZ = 1.0 / Z;
330 _J[2 * index_][0] = -invZ;
331 _J[2 * index_][1] = 0;
332 _J[2 * index_][2] = x_cur * invZ;
333 _J[2 * index_][3] = x_cur * y_cur;
334 _J[2 * index_][4] = -(1 + x_cur * x_cur);
335 _J[2 * index_][5] = y_cur;
337 _J[2 * index_ + 1][0] = 0;
338 _J[2 * index_ + 1][1] = -invZ;
339 _J[2 * index_ + 1][2] = y_cur * invZ;
340 _J[2 * index_ + 1][3] = (1 + y_cur * y_cur);
341 _J[2 * index_ + 1][4] = -y_cur * x_cur;
342 _J[2 * index_ + 1][5] = -x_cur;
344 _R[2 * index_] = (x0_transform - x_cur);
345 _R[2 * index_ + 1] = (y0_transform - y_cur);
358 bool vpMbtDistanceKltCylinder::isTrackedFeature(
int _id)
360 std::map<int, vpImagePoint>::iterator iter = initPoints.find(_id);
361 if (iter != initPoints.end())
376 void vpMbtDistanceKltCylinder::updateMask(
378 unsigned char nb,
unsigned int shiftBorder)
380 int width = mask.cols;
381 int height = mask.rows;
383 for (
unsigned int kc = 0; kc < listIndicesCylinderBBox.size(); kc++) {
384 if ((*hiddenface)[(
unsigned int)listIndicesCylinderBBox[kc]]->isVisible() &&
385 (*hiddenface)[(
unsigned int)listIndicesCylinderBBox[kc]]->getNbPoint() > 2) {
386 int i_min, i_max, j_min, j_max;
387 std::vector<vpImagePoint> roi;
388 (*hiddenface)[(
unsigned int)listIndicesCylinderBBox[kc]]->getRoiClipped(cam, roi);
390 double shiftBorder_d = (double)shiftBorder;
391 #if defined(VISP_HAVE_CLIPPER)
392 std::vector<vpImagePoint> roi_offset;
394 ClipperLib::Path path;
395 for (std::vector<vpImagePoint>::const_iterator it = roi.begin(); it != roi.end(); ++it) {
396 path.push_back(ClipperLib::IntPoint((ClipperLib::cInt)it->get_u(), (ClipperLib::cInt)it->get_v()));
399 ClipperLib::Paths solution;
400 ClipperLib::ClipperOffset co;
401 co.AddPath(path, ClipperLib::jtRound, ClipperLib::etClosedPolygon);
402 co.Execute(solution, -shiftBorder_d);
405 if (!solution.empty()) {
406 size_t index_max = 0;
408 if (solution.size() > 1) {
412 for (
size_t i = 0; i < solution.size(); i++) {
413 std::vector<vpImagePoint> corners;
415 for (
size_t j = 0; j < solution[i].size(); j++) {
416 corners.push_back(
vpImagePoint((
double)(solution[i][j].Y), (
double)(solution[i][j].X)));
420 if (polygon_area.
getArea() > max_area) {
421 max_area = polygon_area.
getArea();
427 for (
size_t i = 0; i < solution[index_max].size(); i++) {
428 roi_offset.push_back(
vpImagePoint((
double)(solution[index_max][i].Y), (
double)(solution[index_max][i].X)));
439 #if defined(VISP_HAVE_CLIPPER)
446 if (i_min > height) {
449 if (i_max > height) {
459 for (
int i = i_min; i < i_max; i++) {
460 double i_d = (double)i;
462 for (
int j = j_min; j < j_max; j++) {
463 double j_d = (double)j;
465 #if defined(VISP_HAVE_CLIPPER)
467 if (polygon_test.isInside(imPt)) {
468 mask.ptr<uchar>(i)[j] = nb;
471 if (shiftBorder != 0) {
477 mask.at<
unsigned char>(i, j) = nb;
482 mask.at<
unsigned char>(i, j) = nb;
499 std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
500 for (; iter != curPoints.end(); ++iter) {
503 iP.
set_i(
static_cast<double>(iter->second.get_i()));
504 iP.
set_j(
static_cast<double>(iter->second.get_j()));
510 std::stringstream ss;
521 void vpMbtDistanceKltCylinder::displayPrimitive(
const vpImage<vpRGBa> &_I)
523 std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
524 for (; iter != curPoints.end(); ++iter) {
527 iP.
set_i(
static_cast<double>(iter->second.get_i()));
528 iP.
set_j(
static_cast<double>(iter->second.get_j()));
534 std::stringstream ss;
544 std::vector<std::vector<double> > models = getModelForDisplay(cMo, camera);
546 for (
size_t i = 0; i < models.size(); i++) {
557 std::vector<std::vector<double> > models = getModelForDisplay(cMo, camera);
559 for (
size_t i = 0; i < models.size(); i++) {
572 std::vector<std::vector<double> > vpMbtDistanceKltCylinder::getFeaturesForDisplay()
574 std::vector<std::vector<double> > features;
576 std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
577 for (; iter != curPoints.end(); ++iter) {
580 iP.
set_i(
static_cast<double>(iter->second.get_i()));
581 iP.
set_j(
static_cast<double>(iter->second.get_j()));
587 std::vector<double> params = { 1,
590 features.push_back(params);
604 std::vector<std::vector<double> > vpMbtDistanceKltCylinder::getModelForDisplay(
const vpHomogeneousMatrix &cMo,
607 std::vector<std::vector<double> > models;
612 circle1.changeFrame(cMo);
613 circle2.changeFrame(cMo);
614 cylinder.changeFrame(cMo);
617 circle1.projection();
620 std::cout <<
"Problem projection circle 1";
623 circle2.projection();
626 std::cout <<
"Problem projection circle 2";
629 cylinder.projection();
639 double i11, i12, i21, i22, j11, j12, j21, j22;
654 std::vector<double> params1 = { 0,
656 models.push_back(params1);
658 std::vector<double> params2 = { 0,
661 models.push_back(params1);
662 models.push_back(params2);
672 double vpMbtDistanceKltCylinder::computeZ(
const double &x,
const double &y)
683 return cylinder.computeZ(x, y);
686 #elif !defined(VISP_BUILD_SHARED_LIBS)
689 void dummy_vpMbtDistanceKltCylinder() { };
Generic class defining intrinsic camera parameters.
static void computeIntersectionPoint(const vpCircle &circle, const vpCameraParameters &cam, const double &rho, const double &theta, double &i, double &j)
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)
Implementation of an homogeneous matrix and operations on such kind of matrices.
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 bool isNaN(double value)
static int round(double x)
Implementation of a matrix and operations on matrices.
static void convertLine(const vpCameraParameters &cam, const double &rho_m, const double &theta_m, double &rho_p, double &theta_p)
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
double get_oX() const
Get the point oX coordinate in the object frame.
double get_y() const
Get the point y coordinate in the image plane.
double get_oZ() const
Get the point oZ coordinate in the object frame.
double get_x() const
Get the point x coordinate in the image plane.
double get_oY() const
Get the point oY coordinate in the object frame.
void changeFrame(const vpHomogeneousMatrix &cMo, vpColVector &cP) const VP_OVERRIDE
void setWorldCoordinates(double oX, double oY, double oZ)
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