00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "ar_pose/ar_multi.h"
00024 #include "ar_pose/object.h"
00025
00026 using namespace cv;
00027 using namespace ar_pose;
00028
00029 int main (int argc, char **argv)
00030 {
00031 ros::init (argc, argv, "ar_single");
00032 ros::NodeHandle n;
00033 ar_pose::ARSinglePublisher ar_single (n);
00034
00035 dynamic_reconfigure::Server<ARSinglePublisherConfig> server;
00036 dynamic_reconfigure::Server<ARSinglePublisherConfig>::CallbackType f;
00037
00038 f = boost::bind(&(ARSinglePublisher::callback), _1, _2);
00039 server.setCallback(f);
00040
00041
00042 ros::spin ();
00043 return 0;
00044 }
00045
00046 namespace ar_pose
00047 {
00048
00049 int ARSinglePublisher::window_size_ = 80;
00050 double ARSinglePublisher::k_ = 0.06;
00051 bool ARSinglePublisher::enable_thresholded_ = false;
00052 bool ARSinglePublisher::enable_hist_ = false;
00053 int ARSinglePublisher::threshold_ = 100;
00054 bool ARSinglePublisher::enable_local_thresh_=false;
00055
00056 void ARSinglePublisher::callback(ARSinglePublisherConfig &config, uint32_t level) {
00057 ROS_INFO("Reconfigure Request: %d %d %d %.2f %d",
00058 config.window_size,
00059 config.enable_hist,
00060 config.enable_thresholded,
00061 config.k,
00062 config.original_thresh,
00063 config.enable_local_thresh);
00064 window_size_ = config.window_size;
00065 enable_hist_ = config.enable_hist;
00066 enable_thresholded_ = config.enable_thresholded;
00067 k_ = config.k;
00068 threshold_ = config.original_thresh;
00069 enable_local_thresh_=config.enable_local_thresh;
00070 }
00071
00072 IplImage * ARSinglePublisher::drawHistogram(IplImage *img)
00073 {
00074 int numBins = 256;
00075 float range[] = {0, 255};
00076 float *ranges[] = { range };
00077 float scaleX = 2, scaleY = 2;
00078 const int width = 3;
00079
00080 CvHistogram *hist = cvCreateHist(1, &numBins, CV_HIST_ARRAY, ranges, 1);
00081 cvClearHist(hist);
00082
00083 IplImage *im_gray = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
00084 cvCvtColor(img, im_gray, CV_RGB2GRAY);
00085
00086 cvCalcHist(&im_gray, hist, 0, 0);
00087 IplImage *imgHistGray = cvCreateImage(cvSize(256*scaleX, 64*scaleY), 8, 3);
00088 cvZero(imgHistGray);
00089
00090 float histMax = 0;
00091 cvGetMinMaxHistValue(hist, 0, &histMax, 0, 0);
00092
00093 for(int i=0;i<255;i++)
00094 {
00095 float histValue = cvQueryHistValue_1D(hist, i);
00096 float nextValue = cvQueryHistValue_1D(hist, i+1);
00097
00098 CvPoint pt1 = cvPoint(i*scaleX, 64*scaleY);
00099 CvPoint pt2 = cvPoint(i*scaleX+scaleX, 64*scaleY);
00100 CvPoint pt3 = cvPoint(i*scaleX+scaleX, (64-nextValue*64/histMax)*scaleY);
00101 CvPoint pt4 = cvPoint(i*scaleX, (64-histValue*64/histMax)*scaleY);
00102
00103 int numPts = 5;
00104 CvPoint pts[] = {pt1, pt2, pt3, pt4, pt1};
00105
00106 cvFillConvexPoly(imgHistGray, pts, numPts, CV_RGB(255,255,255));
00107 }
00108
00109
00110
00111
00112
00113
00114 cvReleaseImage(&im_gray);
00115 cvReleaseHist(&hist);
00116
00117 return imgHistGray;
00118 }
00119
00127 void ARSinglePublisher::localThreshold(Mat& img, Mat& dst, double k, int window)
00128 {
00129 Mat mean(img.size(), CV_32F);
00130 Mat deviation(img.size(), CV_32F);
00131 Mat aux(img.size(), CV_32F);
00132 Mat thresh(img.size(), CV_8U);
00133 boxFilter(img, mean, CV_32F, Size(window, window));
00134 subtract(img, mean, deviation, noArray(), CV_32F);
00135 subtract(Scalar(255), deviation, aux, noArray(), CV_32F);
00136 divide(deviation, aux, aux, 1, CV_32F);
00137 subtract(aux, Scalar(1), aux, noArray(), CV_32F);
00138 multiply(Scalar(k), aux, aux, 1, CV_32F);
00139 add(Scalar(1), aux, aux, noArray(), CV_32F);
00140 multiply(mean, aux, thresh, 1, CV_8U);
00141 dst = img > thresh;
00142 }
00143
00144 ARSinglePublisher::ARSinglePublisher (ros::NodeHandle & n):n_ (n), it_ (n_)
00145 {
00146 std::string local_path;
00147 std::string package_path = ros::package::getPath (ROS_PACKAGE_NAME);
00148 std::string default_path = "data/object_4x4";
00149 ros::NodeHandle n_param ("~");
00150 XmlRpc::XmlRpcValue xml_marker_center;
00151
00152
00153
00154 if (!n_param.getParam ("publish_tf", publishTf_))
00155 publishTf_ = true;
00156 ROS_INFO ("\tPublish transforms: %d", publishTf_);
00157
00158 if (!n_param.getParam ("publish_visual_markers", publishVisualMarkers_))
00159 publishVisualMarkers_ = true;
00160 ROS_INFO ("\tPublish visual markers: %d", publishVisualMarkers_);
00161
00162 if (!n_param.getParam ("threshold", threshold_))
00163
00164 ROS_INFO ("\tThreshold: %d", threshold_);
00165
00166
00167 n_param.param ("marker_pattern_list", local_path, default_path);
00168 if (local_path.compare(0,5,"data/") == 0){
00169
00170 sprintf (pattern_filename_, "%s/%s", package_path.c_str (), local_path.c_str ());
00171 }
00172 else{
00173
00174 sprintf (pattern_filename_, "%s", local_path.c_str ());
00175 }
00176 ROS_INFO ("Marker Pattern Filename: %s", pattern_filename_);
00177
00178
00179
00180 ROS_INFO ("Subscribing to info topic");
00181 sub_ = n_.subscribe (cameraInfoTopic_, 1, &ARSinglePublisher::camInfoCallback, this);
00182 getCamInfo_ = false;
00183
00184
00185
00186 thresholded_ = it_.advertise("thresholded", 1);
00187 histogram_ = it_.advertise("histogram", 1);
00188 arMarkerPub_ = n_.advertise < ar_pose::ARMarkers > ("ar_pose_marker", 0);
00189 if(publishVisualMarkers_)
00190 {
00191 rvizMarkerPub_ = n_.advertise < visualization_msgs::Marker > ("visualization_marker", 0);
00192 }
00193 }
00194
00195 ARSinglePublisher::~ARSinglePublisher (void)
00196 {
00197
00198 arVideoCapStop ();
00199 arVideoClose ();
00200 }
00201
00202 void ARSinglePublisher::camInfoCallback (const sensor_msgs::CameraInfoConstPtr & cam_info)
00203 {
00204 if (!getCamInfo_)
00205 {
00206 cam_info_ = (*cam_info);
00207
00208 cam_param_.xsize = cam_info_.width;
00209 cam_param_.ysize = cam_info_.height;
00210
00211 cam_param_.mat[0][0] = cam_info_.P[0];
00212 cam_param_.mat[1][0] = cam_info_.P[4];
00213 cam_param_.mat[2][0] = cam_info_.P[8];
00214 cam_param_.mat[0][1] = cam_info_.P[1];
00215 cam_param_.mat[1][1] = cam_info_.P[5];
00216 cam_param_.mat[2][1] = cam_info_.P[9];
00217 cam_param_.mat[0][2] = cam_info_.P[2];
00218 cam_param_.mat[1][2] = cam_info_.P[6];
00219 cam_param_.mat[2][2] = cam_info_.P[10];
00220 cam_param_.mat[0][3] = cam_info_.P[3];
00221 cam_param_.mat[1][3] = cam_info_.P[7];
00222 cam_param_.mat[2][3] = cam_info_.P[11];
00223
00224 cam_param_.dist_factor[0] = cam_info_.K[2];
00225 cam_param_.dist_factor[1] = cam_info_.K[5];
00226 cam_param_.dist_factor[2] = -100*cam_info_.D[0];
00227 cam_param_.dist_factor[3] = 1.0;
00228
00229 arInit ();
00230
00231 ROS_INFO ("Subscribing to image topic");
00232 cam_sub_ = it_.subscribe (cameraImageTopic_, 1, &ARSinglePublisher::getTransformationCallback, this);
00233 getCamInfo_ = true;
00234 }
00235 }
00236
00237 void ARSinglePublisher::arInit ()
00238 {
00239 arInitCparam (&cam_param_);
00240 ROS_INFO ("*** Camera Parameter ***");
00241 arParamDisp (&cam_param_);
00242
00243
00244 if ((object = ar_object::read_ObjData (pattern_filename_, &objectnum)) == NULL)
00245 ROS_BREAK ();
00246 ROS_DEBUG ("Objectfile num = %d", objectnum);
00247
00248 sz_ = cvSize (cam_param_.xsize, cam_param_.ysize);
00249 capture_ = cvCreateImage (sz_, IPL_DEPTH_8U, 4);
00250 }
00251
00252 void ARSinglePublisher::getTransformationCallback (const sensor_msgs::ImageConstPtr & image_msg)
00253 {
00254
00255 ARUint8 *dataPtr;
00256 ARMarkerInfo *marker_info;
00257 int marker_num;
00258 int i, k, j, l;
00259
00260
00261
00262
00263
00264 try
00265 {
00266 capture_ = bridge_.imgMsgToCv (image_msg, "bgr8");
00267 }
00268 catch (sensor_msgs::CvBridgeException & e)
00269 {
00270 ROS_ERROR ("Could not convert from '%s' to 'bgr8'.", image_msg->encoding.c_str ());
00271 }
00272
00275
00276 IplImage *hist = NULL;
00277 if (enable_hist_)
00278 hist = drawHistogram(capture_);
00279 IplImage *im_gray = cvCreateImage(cvGetSize(capture_),IPL_DEPTH_8U,1);
00280 cvCvtColor(capture_, im_gray, CV_BGR2GRAY);
00281 Mat gray(im_gray);
00282 Mat thresholded(gray.size(), CV_8U);
00283
00284
00285 if (enable_local_thresh_){
00286 localThreshold(gray, thresholded, k_,
00287 (window_size_ % 2 == 0 ? window_size_ + 1: window_size_));
00288 }
00289 else {
00290 threshold(gray, thresholded, threshold_, 255, THRESH_BINARY);
00291 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 dataPtr = (ARUint8*) malloc(sizeof(ARUint8)*capture_->width*capture_->height*3);
00309 int cnt = 0;
00310 for (int y = 0; y < capture_->height; y++) {
00311 for (int x = 0; x < capture_->width; x++) {
00312 for (int j = 0; j < 3; j++) {
00313 dataPtr[cnt++] = thresholded.at<uchar>(y,x);
00314 }
00315 }
00316 }
00317
00318
00319 if (arDetectMarker (dataPtr, threshold_, &marker_info, &marker_num) < 0)
00320 {
00321 argCleanup ();
00322 ROS_BREAK ();
00323 }
00324
00325 arPoseMarkers_.markers.clear ();
00326
00327 for (i = 0; i < objectnum; i++)
00328 {
00329 k = -1;
00330 l = -1;
00331 for (j = 0; j < marker_num; j++)
00332 {
00333 if (object[i].id == marker_info[j].id)
00334 {
00335 if (k == -1)
00336 k = j;
00337 else
00338 if (marker_info[k].cf < marker_info[j].cf) {
00339 l = k;
00340 k = j;
00341 }
00342 }
00343 }
00344 if (k == -1)
00345 {
00346 object[i].visible = 0;
00347 continue;
00348 }
00349
00350 if (l != -1 && marker_info[k].cf < 2 * marker_info[l].cf)
00351 {
00352 object[i].visible = 0;
00353 continue;
00354 }
00355
00356
00357 if (object[i].visible == 0)
00358 {
00359 arGetTransMat (&marker_info[k], object[i].marker_center, object[i].marker_width, object[i].trans);
00360 }
00361 else
00362 {
00363 arGetTransMatCont (&marker_info[k], object[i].trans,
00364 object[i].marker_center, object[i].marker_width, object[i].trans);
00365 }
00366 object[i].visible = 1;
00367
00368
00369
00370 double arQuat[4], arPos[3];
00371
00372
00373 arUtilMat2QuatPos (object[i].trans, arQuat, arPos);
00374
00375
00376
00377 double quat[4], pos[3];
00378
00379 pos[0] = arPos[0] * AR_TO_ROS;
00380 pos[1] = arPos[1] * AR_TO_ROS;
00381 pos[2] = arPos[2] * AR_TO_ROS;
00382
00383 quat[0] = -arQuat[0];
00384 quat[1] = -arQuat[1];
00385 quat[2] = -arQuat[2];
00386 quat[3] = arQuat[3];
00387
00388 ROS_DEBUG (" Object num %i ------------------------------------------------", i);
00389 ROS_DEBUG (" QUAT: Pos x: %3.5f y: %3.5f z: %3.5f", pos[0], pos[1], pos[2]);
00390 ROS_DEBUG (" Quat qx: %3.5f qy: %3.5f qz: %3.5f qw: %3.5f", quat[0], quat[1], quat[2], quat[3]);
00391
00392
00393
00394 ar_pose::ARMarker ar_pose_marker;
00395 ar_pose_marker.header.frame_id = image_msg->header.frame_id;
00396
00397 ar_pose_marker.header.stamp = image_msg->header.stamp;
00398 ar_pose_marker.id = object[i].id;
00399
00400 ar_pose_marker.pose.pose.position.x = pos[0];
00401 ar_pose_marker.pose.pose.position.y = pos[1];
00402 ar_pose_marker.pose.pose.position.z = pos[2];
00403
00404 ar_pose_marker.pose.pose.orientation.x = quat[0];
00405 ar_pose_marker.pose.pose.orientation.y = quat[1];
00406 ar_pose_marker.pose.pose.orientation.z = quat[2];
00407 ar_pose_marker.pose.pose.orientation.w = quat[3];
00408
00409 ar_pose_marker.confidence = round(marker_info->cf * 100);
00410 arPoseMarkers_.markers.push_back (ar_pose_marker);
00411
00412
00413
00414 btQuaternion rotation (quat[0], quat[1], quat[2], quat[3]);
00415 btVector3 origin (pos[0], pos[1], pos[2]);
00416 btTransform t (rotation, origin);
00417
00418 if (publishTf_)
00419 {
00420 tf::StampedTransform camToMarker (t, image_msg->header.stamp, image_msg->header.frame_id, object[i].name);
00421 broadcaster_.sendTransform(camToMarker);
00422 }
00423
00424
00425
00426 if (publishVisualMarkers_)
00427 {
00428 btVector3 markerOrigin (0, 0, 0.25 * object[i].marker_width * AR_TO_ROS);
00429 btTransform m (btQuaternion::getIdentity (), markerOrigin);
00430 btTransform markerPose = t * m;
00431
00432 tf::poseTFToMsg (markerPose, rvizMarker_.pose);
00433
00434 rvizMarker_.header.frame_id = image_msg->header.frame_id;
00435 rvizMarker_.header.stamp = image_msg->header.stamp;
00436 rvizMarker_.id = object[i].id;
00437
00438 rvizMarker_.scale.x = 1.0 * object[i].marker_width * AR_TO_ROS;
00439 rvizMarker_.scale.y = 1.0 * object[i].marker_width * AR_TO_ROS;
00440 rvizMarker_.scale.z = 0.5 * object[i].marker_width * AR_TO_ROS;
00441 rvizMarker_.ns = "basic_shapes";
00442 rvizMarker_.type = visualization_msgs::Marker::CUBE;
00443 rvizMarker_.action = visualization_msgs::Marker::ADD;
00444 switch (i)
00445 {
00446 case 0:
00447 rvizMarker_.color.r = 0.0f;
00448 rvizMarker_.color.g = 0.0f;
00449 rvizMarker_.color.b = 1.0f;
00450 rvizMarker_.color.a = 1.0;
00451 break;
00452 case 1:
00453 rvizMarker_.color.r = 1.0f;
00454 rvizMarker_.color.g = 0.0f;
00455 rvizMarker_.color.b = 0.0f;
00456 rvizMarker_.color.a = 1.0;
00457 break;
00458 default:
00459 rvizMarker_.color.r = 0.0f;
00460 rvizMarker_.color.g = 1.0f;
00461 rvizMarker_.color.b = 0.0f;
00462 rvizMarker_.color.a = 1.0;
00463 }
00464 rvizMarker_.lifetime = ros::Duration (1);
00465
00466 rvizMarkerPub_.publish (rvizMarker_);
00467 ROS_DEBUG ("Published visual marker");
00468 }
00469 }
00470
00471
00472
00473
00474 if (enable_thresholded_) {
00475 IplImage threshipl = thresholded;
00476 IplImage* iplThresh = &threshipl;
00477 IplImage* color = cvCreateImage(thresholded.size(), IPL_DEPTH_8U, 3);
00478 cvCvtColor(iplThresh, color, CV_GRAY2BGR);
00479
00480 int colorR = 255/(objectnum+1);
00481 for (k = 0; k < marker_num; k++)
00482 {
00483 if (marker_info[k].cf<1 && marker_info[k].cf>0){
00484 const int width = 3;
00485 cvLine(color,cvPoint(marker_info[k].vertex[0][0],marker_info[k].vertex[0][1]),
00486 cvPoint(marker_info[k].vertex[1][0],marker_info[k].vertex[1][1])
00487 ,CV_RGB(colorR*marker_info[k].id, 255-colorR*marker_info[k].id, 50),width);
00488 cvLine(color,cvPoint(marker_info[k].vertex[1][0],marker_info[k].vertex[1][1]),
00489 cvPoint(marker_info[k].vertex[2][0],marker_info[k].vertex[2][1])
00490 ,CV_RGB(colorR*marker_info[k].id, 255-colorR*marker_info[k].id, 50),width);
00491 cvLine(color,cvPoint(marker_info[k].vertex[2][0],marker_info[k].vertex[2][1]),
00492 cvPoint(marker_info[k].vertex[3][0],marker_info[k].vertex[3][1])
00493 ,CV_RGB(colorR*marker_info[k].id, 255-colorR*marker_info[k].id, 50),width);
00494 cvLine(color,cvPoint(marker_info[k].vertex[3][0],marker_info[k].vertex[3][1]),
00495 cvPoint(marker_info[k].vertex[0][0],marker_info[k].vertex[0][1])
00496 ,CV_RGB(colorR*marker_info[k].id, 255-colorR*marker_info[k].id, 50),width);
00497 }
00498 }
00499
00500 sensor_msgs::ImagePtr threshPtr = sensor_msgs::CvBridge::cvToImgMsg(color, "passthrough");
00501
00502
00503 threshPtr->header=image_msg->header;
00504
00505 thresholded_.publish(threshPtr);
00506
00507 cvReleaseImage(&color);
00508
00509 }
00510
00511 if (enable_hist_) {
00512 sensor_msgs::ImagePtr histPtr = sensor_msgs::CvBridge::cvToImgMsg(hist, "passthrough");
00513 histPtr->header=image_msg->header;
00514 histogram_.publish(histPtr);
00515 }
00516
00517
00518 cvReleaseImage(&im_gray);
00519 cvReleaseImage(&hist);
00520 free(dataPtr);
00521
00522
00523 arMarkerPub_.publish (arPoseMarkers_);
00524 ROS_DEBUG ("Published ar_multi markers");
00525 }
00526
00527
00528 }