188 DoHandleTest(
int _type_id=-1,
bool _needs_has_p2d=
false,
bool _needs_has_p3d=
false)
189 : type_id(_type_id), needs_has_p2d(_needs_has_p2d), needs_has_p3d(_needs_has_p3d) {}
191 if (needs_has_p2d && !f.has_p2d)
return false;
192 if (needs_has_p3d && !f.has_p3d)
return false;
194 if ((type_id != -1) && (type_id != f.type_id))
return false;
213 DoEraseTest(
bool _erase_without_p2d,
bool _erase_without_p3d,
int _type_id=-1)
214 : type_id(_type_id), erase_without_p2d(_erase_without_p2d), erase_without_p3d(_erase_without_p3d),
215 test_reprojection(false), limit_sq(0.
f) {}
216 DoEraseTest(
float _limit,
bool _erase_without_p2d=
false,
bool _erase_without_p3d=
false,
int _type_id=-1)
217 : type_id(_type_id), erase_without_p2d(_erase_without_p2d), erase_without_p3d(_erase_without_p3d),
218 test_reprojection(true), limit_sq(_limit*_limit) {}
220 if ((type_id != -1) && (type_id != f.type_id))
return false;
221 if (erase_without_p2d && !f.has_p2d)
return true;
222 if (erase_without_p3d && !f.has_p3d)
return true;
223 if (test_reprojection) {
224 if (!f.has_p2d)
return false;
225 if (!f.has_p3d)
return false;
227 double dist_sq = (f.p2d.x-f.projected_p2d.x)*(f.p2d.x-f.projected_p2d.x);
228 dist_sq += (f.p2d.y-f.projected_p2d.y)*(f.p2d.y-f.projected_p2d.y);
229 if (dist_sq > limit_sq)
237 template<
typename T,
typename F>
240 typename std::map<int,T>::iterator iter = container.begin();
241 while(iter != container.end()) {
243 if (do_erase_test(f)) {
244 container.erase(iter++);
257 TrackerFeaturesEC(
int _max_features=100,
int _min_features=90,
double _quality_level=0.01,
double _min_distance=10,
int _pyr_levels=4,
int win_size=6)
258 :
TrackerFeatures(_max_features, _min_features, _quality_level, _min_distance, _pyr_levels, win_size), purge(false) {}
262 bool Track(IplImage *img, IplImage *mask, std::map<int,T> &container,
int type_id=-1,
int first_id=-1,
int last_id=-1)
266 return Track(img, mask, container, do_handle_test_default,
type_id, first_id, last_id);
310 template<
typename T,
typename F>
311 bool Track(IplImage *img, IplImage *mask, std::map<int,T> &container, F do_handle_test,
int type_id=0,
int first_id=-1,
int last_id=-1)
314 if (first_id < 0) last_id = -1;
316 typename std::map<int,T>::iterator iter = container.begin();
317 typename std::map<int,T>::iterator iter_end = container.end();
319 for (;iter != iter_end; iter++) {
321 if (!do_handle_test(f))
continue;
322 if (f.has_p2d !=
true)
continue;
324 features[feature_count] = f.p2d;
325 ids[feature_count] = iter->first;
327 if (feature_count == max_features)
break;
336 TrackHid(img, mask,
false);
339 if (next_id < first_id) next_id = first_id;
340 if (next_id > last_id)
return false;
342 TrackHid(img, mask,
true);
345 for (
int i=0; i<feature_count; i++) {
347 if (last_id >= 0 &&
id >= last_id)
break;
348 T &
f = container[id];
362 for (
int i=0; i<feature_count; i++) {
364 if (last_id >= 0 &&
id >= last_id)
break;
365 T &
f = container[id];
398 return Undistort(container, do_handle_test_default);
401 template<
typename T,
typename F>
402 void Undistort(std::map<int,T> &container, F &do_handle_test) {
403 typename std::map<int,T>::iterator iter = container.begin();
404 typename std::map<int,T>::iterator iter_end = container.end();
405 for (;iter != iter_end; iter++) {
407 if (!do_handle(f))
continue;
408 if (f.has_p2d) Undistort(f.p2d);
415 return Distort(container, do_handle_test_default);
418 template<
typename T,
typename F>
419 void Distort(std::map<int,T> &container, F &do_handle_test) {
420 typename std::map<int,T>::iterator iter = container.begin();
421 typename std::map<int,T>::iterator iter_end = container.end();
422 for (;iter != iter_end; iter++) {
424 if (!do_handle(f))
continue;
425 if (f.has_p2d) Distort(f.p2d);
432 return CalcExteriorOrientation(container, pose, do_handle_test_default);
435 template<
typename T,
typename F>
437 int count_points = container.size();
438 if(count_points < 4)
return false;
439 CvMat* world_points = cvCreateMat(count_points, 1, CV_32FC3);
440 CvMat* image_observations = cvCreateMat(count_points*2, 1, CV_32FC2);
441 typename std::map<int,T>::iterator iter = container.begin();
442 typename std::map<int,T>::iterator iter_end = container.end();
444 for (;iter != iter_end; iter++) {
446 if (!do_handle_test(f))
continue;
447 if (f.has_p2d && f.has_p3d) {
448 world_points->data.fl[ind*3+0] = (float)f.p3d.x;
449 world_points->data.fl[ind*3+1] = (
float)f.p3d.y;
450 world_points->data.fl[ind*3+2] = (float)f.p3d.z;
451 image_observations->data.fl[ind*2+0] = (
float)f.p2d.x;
452 image_observations->data.fl[ind*2+1] = (float)f.p2d.y;
456 if (ind<4)
return false;
458 CvRect
r; r.x = 0; r.y = 0; r.height = ind; r.width = 1;
459 CvMat world_points_sub;
460 cvGetSubRect(world_points, &world_points_sub, r);
461 CvMat image_observations_sub;
462 cvGetSubRect(image_observations, &image_observations_sub, r);
466 cvReleaseMat(&image_observations);
467 cvReleaseMat(&world_points);
475 return UpdatePose(container, pose, do_handle_test_default, weights);
481 return UpdateRotation(container, pose, do_handle_test_default);
484 template<
typename T,
typename F>
486 int count_points = container.size();
487 if(count_points < 6)
return false;
489 CvMat* world_points = cvCreateMat(count_points, 1, CV_64FC3);
490 CvMat* image_observations = cvCreateMat(count_points*2, 1, CV_64F);
493 typename std::map<int,T>::iterator iter = container.begin();
494 typename std::map<int,T>::iterator iter_end = container.end();
495 for (;iter != iter_end; iter++) {
497 if (!do_handle_test(f))
continue;
498 if (f.has_p2d && f.has_p3d) {
499 world_points->data.db[ind*3+0] = f.p3d.x;
500 world_points->data.db[ind*3+1] = f.p3d.y;
501 world_points->data.db[ind*3+2] = f.p3d.z;
502 image_observations->data.db[ind*2+0] = f.p2d.x;
503 image_observations->data.db[ind*2+1] = f.p2d.y;
507 if (ind < 6)
return false;
509 CvRect
r; r.x = 0; r.y = 0; r.height = ind; r.width = 1;
510 CvMat world_points_sub;
511 cvGetSubRect(world_points, &world_points_sub, r);
514 CvMat image_observations_sub;
515 cvGetSubRect(image_observations, &image_observations_sub, r);
517 bool ret = UpdateRotation(&world_points_sub, &image_observations_sub, pose);
519 cvReleaseMat(&image_observations);
520 cvReleaseMat(&world_points);
525 template<
typename T,
typename F>
526 bool UpdatePose(std::map<int,T> &container,
Pose *pose, F do_handle_test, std::map<int,double> *weights=0) {
527 int count_points = container.size();
528 if(count_points < 4)
return false;
530 CvMat* world_points = cvCreateMat(count_points, 1, CV_64FC3);
531 CvMat* image_observations = cvCreateMat(count_points*2, 1, CV_64F);
533 if(weights) w = cvCreateMat(count_points*2, 1, CV_64F);
536 typename std::map<int,T>::iterator iter = container.begin();
537 typename std::map<int,T>::iterator iter_end = container.end();
538 for (;iter != iter_end; iter++) {
540 if (!do_handle_test(f))
continue;
541 if (f.has_p2d && f.has_p3d) {
542 world_points->data.db[ind*3+0] = f.p3d.x;
543 world_points->data.db[ind*3+1] = f.p3d.y;
544 world_points->data.db[ind*3+2] = f.p3d.z;
545 image_observations->data.db[ind*2+0] = f.p2d.x;
546 image_observations->data.db[ind*2+1] = f.p2d.y;
549 w->data.db[ind*2+1] = w->data.db[ind*2+0] = (*weights)[iter->first];
553 if (ind < 4)
return false;
555 CvRect
r; r.x = 0; r.y = 0; r.height = ind; r.width = 1;
556 CvMat world_points_sub;
557 cvGetSubRect(world_points, &world_points_sub, r);
560 CvMat image_observations_sub;
561 cvGetSubRect(image_observations, &image_observations_sub, r);
566 cvGetSubRect(w, &w_sub, r);
567 ret = UpdatePose(&world_points_sub, &image_observations_sub, pose, &w_sub);
570 ret = UpdatePose(&world_points_sub, &image_observations_sub, pose);
572 cvReleaseMat(&image_observations);
573 cvReleaseMat(&world_points);
574 if(w) cvReleaseMat(&w);
581 float Reproject(std::map<int,T> &container,
Pose *pose,
int type_id=-1,
bool needs_has_p2d=
false,
bool needs_has_p3d=
false,
float average_outlier_limit=0.f)
584 return Reproject(container, pose, do_handle_test, average_outlier_limit);
587 template<
typename T,
typename F>
588 float Reproject(std::map<int,T> &container,
Pose *pose, F do_handle_test,
float average_outlier_limit=0.f)
590 float reprojection_sum=0.f;
591 int reprojection_count=0;
592 float limit_sq = average_outlier_limit*average_outlier_limit;
593 typename std::map<int,T>::iterator iter = container.begin();
594 typename std::map<int,T>::iterator iter_end = container.end();
595 for(;iter != iter_end;iter++) {
597 if (!do_handle_test(f))
continue;
602 float dist_sq = (f.p2d.x-f.projected_p2d.x)*(f.p2d.x-f.projected_p2d.x);
603 dist_sq += (f.p2d.y-f.projected_p2d.y)*(f.p2d.y-f.projected_p2d.y);
604 if ((limit_sq == 0) || (dist_sq < limit_sq)) {
605 reprojection_sum += sqrt(dist_sq);
606 reprojection_count++;
609 if (reprojection_count == 0)
return 0.f;
610 return reprojection_sum/reprojection_count;
620 if (pose) Reproject(container, pose,
type_id,
false,
false);
626 bool UpdateRotation(
const CvMat* object_points, CvMat* image_points,
Pose *pose);
629 bool UpdateRotation(
const CvMat* object_points, CvMat* image_points, CvMat *rot, CvMat *tra);
632 bool UpdatePose(
const CvMat* object_points, CvMat* image_points,
Pose *pose, CvMat *weights=0);
635 bool UpdatePose(
const CvMat* object_points, CvMat* image_points, CvMat *rodriques, CvMat *tra, CvMat *weights=0);
638 bool ReconstructFeature(
const Pose *pose1,
const Pose *pose2,
const CvPoint2D32f *u1,
const CvPoint2D32f *u2, CvPoint3D32f *
p3d,
double limit);
641 void Get3dOnPlane(
const Pose *pose, CvPoint2D32f
p2d, CvPoint3D32f &p3d);
644 void Get3dOnDepth(
const Pose *pose, CvPoint2D32f p2d,
float depth, CvPoint3D32f &p3d);
649 int id = first_id + marker_id*4 + corner_id;
650 if (
id > last_id)
return -1;
660 return PreDetect(p.second, type_id);
664 if (p.type_id != type_id)
return false;
669 int GetId(
int marker_id,
int corner_id,
int first_id=0,
int last_id=65535) {
677 std::map<int,T> &container,
685 LabelingMethod labeling_method=CVSEQ)
690 typename std::map<int,T>::iterator iter = container.begin();
691 typename std::map<int,T>::iterator iter_end = container.end();
692 for (;iter != iter_end; iter++) {
694 if (f.type_id !=
type_id)
continue;
702 for (
size_t i=0; i<MarkerDetector<M>::markers->size(); i++) {
704 for (
int corner=0; corner<4; corner++) {
707 T &
f = container[id];
710 f.p2d.x = float(m.marker_corners_img[corner].x);
711 f.p2d.y = float(m.marker_corners_img[corner].y);
720 void MarkerToEC(std::map<int,T> &container,
int marker_id,
double edge_length,
Pose &pose,
int type_id=0,
int first_id=0,
int last_id=65535) {
721 CvMat *m3 = cvCreateMat(4,4,CV_64F); cvSetIdentity(m3);
724 for(
size_t corner = 0; corner < 4; ++corner)
728 double X_data[4] = {0, 0, 0, 1};
730 X_data[0] = -0.5*edge_length;
731 X_data[1] = -0.5*edge_length;
732 }
else if (corner == 1) {
733 X_data[0] = +0.5*edge_length;
734 X_data[1] = -0.5*edge_length;
735 }
else if (corner == 2) {
736 X_data[0] = +0.5*edge_length;
737 X_data[1] = +0.5*edge_length;
738 }
else if (corner == 3) {
739 X_data[0] = -0.5*edge_length;
740 X_data[1] = +0.5*edge_length;
743 CvMat X = cvMat(4, 1, CV_64F, X_data);
744 cvMatMul(m3, &X, &X);
747 T &
f = container[id];
749 f.p3d.x = float(X_data[0] / X_data[3]);
750 f.p3d.y = float(X_data[1] / X_data[3]);
751 f.p3d.z = float(X_data[2] / X_data[3]);
765 for (
size_t i = 0; i < marker_indices.size(); i++) {
766 if (marker_status[i] == 0)
continue;
767 int marker_id = marker_indices[i];
768 for (
int corner = 0; corner < 4; corner++) {
771 int pc_index = pointcloud_index(marker_id, corner);
772 T &
f = container[id];
774 f.p3d.x = float(pointcloud[pc_index].
x);
775 f.p3d.y = float(pointcloud[pc_index].
y);
776 f.p3d.z = float(pointcloud[pc_index].
z);
793 if (!MarkersFromEC(container,
type_id, first_id, last_id))
return false;
802 return MarkersToEC(container,
type_id, first_id, last_id);
double max_new_marker_error
This file implements a camera used for projecting points and computing homographies.
bool UpdatePose(std::map< int, T > &container, Pose *pose, int type_id=-1, std::map< int, double > *weights=0)
Update the pose using the items with matching type_id.
bool DelFeatureId(int id)
void Undistort(std::map< int, T > &container, F &do_handle_test)
Undistort the items matching the given functor.
bool MarkersFromEC(std::map< int, T > &container, int type_id=0, int first_id=0, int last_id=65535)
This is a default functor for testing which items in the container should be handled by each method...
bool AddFeatures(std::map< int, T > &container, int type_id=0, int first_id=0, int last_id=65535)
add features to the previously tracked frame if there are less than min_features
Version of Camera using external container.
This file implements a generic marker detector.
bool Track(IplImage *img, IplImage *mask, std::map< int, T > &container, int type_id=-1, int first_id=-1, int last_id=-1)
Track features with matching type id. New features will have id's in the specified id range...
int EraseNonTracked(std::map< int, T > &container, int type_id=-1)
Erases the items matching with type_id having has_p2d == false . If type_id == -1 doesn't test the ty...
ExternalContainer(const ExternalContainer &c)
DoEraseTest(float _limit, bool _erase_without_p2d=false, bool _erase_without_p3d=false, int _type_id=-1)
Base class for using MultiMarker.
TFSIMD_FORCE_INLINE const tfScalar & y() const
float Reproject(std::map< int, T > &container, Pose *pose, int type_id=-1, bool needs_has_p2d=false, bool needs_has_p3d=false, float average_outlier_limit=0.f)
Projects p3d in the items matching with type_id into projected_p2d . If type_id == -1 doesn't test th...
Simple Camera class for calculating distortions, orientation or projections with pre-calibrated camer...
double Reset(IplImage *img, IplImage *mask)
int Purge()
Purge features that are considerably closer than the defined min_distance.
TrackerFeaturesEC(int _max_features=100, int _min_features=90, double _quality_level=0.01, double _min_distance=10, int _pyr_levels=4, int win_size=6)
Constructor.
void Distort(std::map< int, T > &container, int type_id=-1)
Distort the items with matching type_id.
bool PreDetect(T &p, int type_id)
DoHandleTest(int _type_id=-1, bool _needs_has_p2d=false, bool _needs_has_p3d=false)
This is default functor for testing which items in the container should be erased.
Version of MarkerDetector using external container.
Version of MultiMarker using external container.
void Purge()
Purge features that are considerably closer than the defined min_distance.
int GetId(int marker_id, int corner_id, int first_id=0, int last_id=65535)
bool Track(IplImage *img, IplImage *mask, std::map< int, T > &container, F do_handle_test, int type_id=0, int first_id=-1, int last_id=-1)
Track features matching the given functor. New features will have id's in the specified id range...
int AddFeatures(IplImage *mask=NULL)
add features to the previously tracked frame if there are less than min_features
MarkerDetector for detecting markers of type M
void MarkerToEC(std::map< int, T > &container, int marker_id, double edge_length, Pose &pose, int type_id=0, int first_id=0, int last_id=65535)
Fill in 3D-coordinates for marker_id marker corners using edge_length and pose.
DoEraseTest(bool _erase_without_p2d, bool _erase_without_p3d, int _type_id=-1)
void Undistort(std::map< int, T > &container, int type_id=-1)
Undistort the items with matching type_id.
bool Save(std::map< int, T > &container, const char *fname, FILE_FORMAT format=FILE_FORMAT_DEFAULT, int type_id=0, int first_id=0, int last_id=65535)
int EraseItemsEC(std::map< int, T > &container, F do_erase_test)
Erasing items from container using DoEraseTest type functor.
This file implements a feature tracker.
int EraseUsingReprojectionError(std::map< int, T > &container, float reprojection_error_limit, int type_id=-1, Pose *pose=0)
Erases the items matching with type_id having large reprojection error. If type_id == -1 doesn't test...
void ProjectPoint(const CvPoint3D64f pw, const Pose *pose, CvPoint2D64f &pi) const
Project one point.
Pose representation derived from the Rotation class
bool UpdateRotation(std::map< int, T > &container, Pose *pose, F do_handle_test)
Update the rotation in pose using the items matching the given functor.
TFSIMD_FORCE_INLINE const tfScalar & x() const
bool UpdatePose(std::map< int, T > &container, Pose *pose, F do_handle_test, std::map< int, double > *weights=0)
Update the pose using the items matching the given functor.
TrackerFeatures tracks features using OpenCV's cvGoodFeaturesToTrack and cvCalcOpticalFlowPyrLK ...
TFSIMD_FORCE_INLINE const tfScalar & z() const
bool DelFeature(int index)
int Detect(IplImage *image, Camera *cam, std::map< int, T > &container, int type_id=0, int first_id=0, int last_id=65535, bool track=false, bool visualize=false, double max_new_marker_error=0.08, double max_track_error=0.2, LabelingMethod labeling_method=CVSEQ)
Detect markers in the image and fill in their 2D-positions in the given external container.
bool PreDetect(std::pair< const int, T > &p, int type_id)
TFSIMD_FORCE_INLINE const tfScalar & w() const
This file implements a multi-marker.
void GetMatrix(CvMat *mat) const
bool Load(const char *fname, FILE_FORMAT format=FILE_FORMAT_DEFAULT)
Loads multi marker configuration from a text file.
void CalcExteriorOrientation(std::vector< CvPoint3D64f > &pw, std::vector< CvPoint2D64f > &pi, Pose *pose)
Calculate exterior orientation.
bool Load(std::map< int, T > &container, const char *fname, FILE_FORMAT format=FILE_FORMAT_DEFAULT, int type_id=0, int first_id=0, int last_id=65535)
Fill in 3D-coordinates for marker corners to the given container using save MultiMarker file...
int Detect(IplImage *image, Camera *cam, bool track=false, bool visualize=false, double max_new_marker_error=0.08, double max_track_error=0.2, LabelingMethod labeling_method=CVSEQ, bool update_pose=true)
Detect Marker 's from image
void Distort(std::map< int, T > &container, F &do_handle_test)
Distort the items matching the given functor.
bool CalcExteriorOrientation(std::map< int, T > &container, Pose *pose, int type_id=-1)
Calculate the pose using the items with matching type_id.
bool MarkersToEC(std::map< int, T > &container, int type_id=0, int first_id=0, int last_id=65535)
Fill in 3D-coordinates for marker corners to the given container.
CvPoint2D32f projected_p2d
Basic structure to be usable with EC methods.
bool CalcExteriorOrientation(std::map< int, T > &container, Pose *pose, F do_handle_test)
Calculate the pose using the items matching the given functor.
bool UpdateRotation(std::map< int, T > &container, Pose *pose, int type_id=-1)
Update the rotation in pose using the items with matching type_id.
virtual bool operator()(const T &f) const
int MarkerIdToContainerId(int marker_id, int corner_id, int first_id=0, int last_id=65535)
Calculate the index used in external container map for specified marker_id.
bool Save(const char *fname, FILE_FORMAT format=FILE_FORMAT_DEFAULT)
Saves multi marker configuration to a text file.
float Reproject(std::map< int, T > &container, Pose *pose, F do_handle_test, float average_outlier_limit=0.f)
Projects p3d in the items matching with the given functor.
virtual bool operator()(const T &f) const
Version of TrackerFeatures using external container.