00001 #include <iostream>
00002 #include <vector>
00003 #include <list>
00004 #include <math.h>
00005
00006 #include "Motion/Kinematics.h"
00007
00008 #include "SketchSpace.h"
00009 #include "Sketch.h"
00010 #include "ShapeRoot.h"
00011 #include "LineData.h"
00012 #include "Region.h"
00013 #include "visops.h"
00014
00015 #include "SphereData.h"
00016 #include "ShapeSphere.h"
00017
00018 using namespace std;
00019
00020 namespace DualCoding {
00021
00022 SphereData::SphereData(ShapeSpace& _space, const Point &c, float r)
00023 : BaseData(_space,sphereDataType),
00024 centroid(c), radius(r)
00025 { mobile = SPHERE_DATA_MOBILE; }
00026
00027 SphereData::SphereData(const SphereData& otherData)
00028 : BaseData(otherData),centroid(otherData.centroid),radius(otherData.radius)
00029 { mobile = otherData.mobile; }
00030
00031 DATASTUFF_CC(SphereData);
00032
00033 bool SphereData::isMatchFor(const ShapeRoot& other) const {
00034 if (!(isSameTypeAs(other) && isSameColorAs(other)))
00035 return false;
00036 const Shape<SphereData>& other_sphere = ShapeRootTypeConst(other,SphereData);
00037 float dist = centroid.distanceFrom(other_sphere->centerPt());
00038 return dist < 2*max(radius,other_sphere->radius);
00039 }
00040
00041 void SphereData::mergeWith(const ShapeRoot& other) {
00042 const Shape<SphereData>& other_sphere = ShapeRootTypeConst(other,SphereData);
00043 if (other_sphere->confidence <= 0)
00044 return;
00045 const int other_conf = other_sphere->confidence;
00046 confidence += other_conf;
00047 centroid = (centroid*confidence + other_sphere->centerPt()*other_conf) / (confidence+other_conf);
00048 radius = (radius*confidence + other_sphere->getRadius()*other_conf) / (confidence+other_conf);
00049 }
00050
00051 bool SphereData::updateParams(const ShapeRoot& other, bool) {
00052 const Shape<SphereData>& other_sphere = *static_cast<const Shape<SphereData>*>(&other);
00053 centroid = (centroid*(confidence-1) + other_sphere->getCentroid())/confidence;
00054 radius = (radius*(confidence-1) + other_sphere->getRadius())/confidence;
00055 return true;
00056 }
00057
00058
00059 void SphereData::printParams() const {
00060 cout << "Type = " << getTypeName();
00061 cout << "Shape ID = " << getId() << endl;
00062 cout << "Parent ID = " << getParentId() << endl;
00063
00064
00065 cout << endl;
00066 cout << "center{" << centerPt().coordX() << ", " << centerPt().coordY() << "}" << endl;
00067
00068 cout << "radius = " << getRadius() << endl;
00069 printf("color = %d %d %d\n",getColor().red,getColor().green,getColor().blue);
00070 cout << "mobile = " << getMobile() << endl;
00071 cout << "viewable = " << isViewable() << endl;
00072 }
00073
00074
00075
00076 void SphereData::applyTransform(const fmat::Transform& Tmat, const ReferenceFrameType_t newref) {
00077 centroid.applyTransform(Tmat,newref);
00078 }
00079
00080 bool SphereData::isInside(const Point& pt) const {
00081 float dist = pt.distanceFrom(centerPt());
00082 return radius>dist;
00083 }
00084
00085
00086 void SphereData::projectToGround(const fmat::Transform& camToBase, const PlaneEquation& groundplane) {
00087 #ifdef TGT_HAS_CAMERA
00088 fmat::Column<3> cam_pos = kine->linkToBase(CameraFrameOffset).translation();
00089 #else
00090
00091 fmat::Column<3> cam_pos = camToBase.translation();
00092 #endif
00093 cout << "cam position " << cam_pos << endl;
00094 Point tangent_pt(centroid.coordX(),centroid.coordY()+radius, centroid.coordZ());
00095 Point cam_pt(cam_pos);
00096 cout << "sphere in cam frame: centroid:" << "(" << centroid.coordX()
00097 << "," << centroid.coordY() << "," << centroid.coordZ() << "); tangent_pt:"
00098 << "(" << tangent_pt.coordX() << "," << tangent_pt.coordY() << "," << tangent_pt.coordZ()
00099 << ")" << endl;
00100
00101 centroid.projectToGround(camToBase,groundplane);
00102 tangent_pt.projectToGround(camToBase,groundplane);
00103 cout << "sphere projected to ground: centroid:" << "(" << centroid.coordX()
00104 << "," << centroid.coordY() << "," << centroid.coordZ() << "); tangent_pt:"
00105 << "(" << tangent_pt.coordX() << "," << tangent_pt.coordY() << "," << tangent_pt.coordZ()
00106 << ")" << endl;
00107
00108 LineData tangent_line(getSpace(), cam_pt, tangent_pt);
00109 LineData cam_center(getSpace(), cam_pt, centroid);
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 vector<float> t_abc_xz = tangent_line.lineEquation_abc_xz();
00122 vector<float> cc_abc_xz = cam_center.lineEquation_abc_xz();
00123 vector<float> cc_abc_xy = cam_center.lineEquation_abc();
00124
00125 const float f = cc_abc_xz[2] / cc_abc_xz[1];
00126 const float e = - cc_abc_xz[0] / cc_abc_xz[1];
00127 const float d = t_abc_xz[2] / t_abc_xz[1];
00128 const float c = - t_abc_xz[0] / t_abc_xz[1];
00129 const float a = -1.f / e;
00130 const float ground = 1.f/groundplane.getDisplacement();
00131 const float DXtoR = 1.f / std::cos(std::atan(a)) / std::cos(std::atan(-cc_abc_xy[0]/cc_abc_xy[1]));
00132 const float b = (-DXtoR*f*a+DXtoR*f*c+DXtoR*d*a-DXtoR*d*e+ground*a*a-ground*a*c-ground*e*a+ground*e*c-d*a*a+d*e*a)/(-a*c+e*c+DXtoR*c-DXtoR*e);
00133
00134 cout << "ground level: " << ground << ", DXtoR: " << DXtoR << endl;
00135 cout << "tangent line: z = " << e << " * x + " << f << endl;
00136 cout << "perpendicular line: z = " << a << " * x + " << b << endl;
00137 cout << "center line: z = " << c << " * x + " << d << endl;
00138 cout << "dx b/w tangent pt and center pt: " << ((f-b)/(a-e)-(d-b)/(a-c)) << endl;
00139
00140 const float x = (d-b)/(a-c);
00141 const float z = d + c*(d-b)/(a-c);
00142 const float y = (cc_abc_xy[2]-cc_abc_xy[0]*x) / cc_abc_xy[1];
00143
00144 centroid.setCoords(x,y,z);
00145 centroid.setRefFrameType(egocentric);
00146 radius = z-ground;
00147
00148 cout << " => (" << x << "," << y << "," << z << "); radius: " << radius << endl;
00149 }
00150
00151 void SphereData::setRadius(float _radius) {
00152 radius = _radius;
00153 deleteRendering();
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 std::vector<Shape<SphereData> > SphereData::extractSpheres(const Sketch<bool>& sketch)
00166 {
00167 const float AREA_TOLERANCE = 0.5f;
00168 const int REGION_THRESH = 25;
00169 NEW_SKETCH_N(labels,uint,visops::oldlabelcc(sketch,visops::EightWayConnect));
00170 list<Region> regionlist = Region::extractRegions(labels,REGION_THRESH);
00171 std::vector<Shape<SphereData> > spheres;
00172
00173 if(regionlist.empty())
00174 return spheres;
00175
00176 typedef list<Region>::iterator R_IT;
00177 for (R_IT it = regionlist.begin(); it != regionlist.end(); ++it) {
00178 float ratio = it->findSemiMajorAxisLength()/(float)(it->findSemiMinorAxisLength());
00179 if((ratio < 2.0) && (ratio > 1.0/(float)2.0)
00180 && (it->findArea() > M_PI*2.0*(it->findSemiMajorAxisLength())
00181 *2.0*(it->findSemiMinorAxisLength())*AREA_TOLERANCE/4.0)) {
00182 Shape<SphereData> temp_sphere(*it);
00183 temp_sphere->inheritFrom(*sketch.operator->());
00184
00185
00186 spheres.push_back(Shape<SphereData>(temp_sphere));
00187 };
00188 }
00189 return spheres;
00190 }
00191
00192 std::vector<Shape<SphereData> > SphereData::get_spheres(const Sketch<CMVision::uchar>& cam) {
00193
00194 std::vector<bool> Valid_Colors;
00195 Valid_Colors.resize(ProjectInterface::getNumColors(),true);
00196 return(get_spheres(cam,Valid_Colors));
00197 }
00198
00199 std::vector<Shape<SphereData> > SphereData::get_spheres(const Sketch<CMVision::uchar>& cam,
00200 std::vector<bool>& Valid_Colors) {
00201 std::vector<Shape<SphereData> > spheres_vec;
00202 uchar cur_color;
00203 uchar num_colors = (uchar)Valid_Colors.size();
00204 char *pmask_name_chr = (char *)malloc(128*sizeof(char));
00205
00206
00207 for(cur_color = 0; cur_color < num_colors; cur_color++) {
00208
00209 if(Valid_Colors[cur_color] == true) {
00210
00211
00212 NEW_SKETCH_N(pmask, bool, visops::colormask(cam,cur_color));
00213 sprintf(pmask_name_chr, "pmask_%d",cur_color);
00214 pmask->setName(pmask_name_chr);
00215
00216
00217 std::vector<Shape<SphereData> > spheresList = SphereData::extractSpheres(pmask);
00218
00219 int num_spheres = (int)spheresList.size();
00220 int cur_sphere;
00221
00222 for(cur_sphere = 0; cur_sphere < num_spheres; cur_sphere++) {
00223
00224 spheres_vec.push_back(spheresList[cur_sphere]);
00225 }
00226
00227 };
00228 }
00229 return(spheres_vec);
00230 }
00231
00232
00233
00234 Sketch<bool>* SphereData::render() const {
00235 const int cx = int(centerPt().coordX());
00236 const int cy = int(centerPt().coordY());
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 Sketch<bool> result(space->getDualSpace(), "render("+getName()+")");
00256 result = 0;
00257 const int rad =(int) floor(getRadius()+0.5);
00258 const int radSq = rad*rad + rad/10;
00259 const int minX = (rad > cx) ? 0 : cx-rad;
00260 const int maxX = ((unsigned int) (rad+cx) > getSpace().getDualSpace().getWidth()-1)
00261 ? getSpace().getDualSpace().getWidth()-1 : (unsigned int)(cx+rad);
00262 for (int x = minX; x <= maxX; x++) {
00263 const int yRange = (int) sqrt((float) (radSq-(cx-x)*(cx-x)));
00264 const int minY = (yRange > cy) ? 0 : cy-yRange;
00265 const int maxY = ((unsigned int) yRange+cy > getSpace().getDualSpace().getHeight()-1)
00266 ? getSpace().getDualSpace().getHeight()-1 : (unsigned int)(cy+yRange);
00267 for (int y = minY; y <= maxY; y++)
00268 result(x,y) = true;
00269 }
00270 return new Sketch<bool>(result);
00271 }
00272
00273
00274 }