00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <ucl_drone/computer_vision/computer_vision.h>
00014
00016 static const std::string PKG_DIR = ros::package::getPath("ucl_drone");
00017
00018 #if EXTRACTOR_TYPE == TYPE_ORB
00019 Target::Target() : matcher(new cv::flann::LshIndexParams(20, 10, 2))
00020 #else
00021 Target::Target()
00022 #endif
00023 {
00024 }
00025
00026 Target::~Target()
00027 {
00028 }
00029
00030 bool Target::init(const std::string relative_path)
00031 {
00032
00033 std::string str = PKG_DIR + relative_path;
00034 ROS_INFO("%s", str.c_str());
00035 cv::Mat target_img = cv::imread(str.c_str(), CV_LOAD_IMAGE_COLOR);
00036
00037 if (!target_img.data)
00038 {
00039 ROS_INFO("Could not open or find the image");
00040 return false;
00041 };
00042
00043 image = target_img;
00044
00045
00046
00047 centerAndCorners.resize(5);
00048 centerAndCorners[0] = cv::Point(0, 0);
00049 centerAndCorners[1] = cv::Point(image.cols, 0);
00050 centerAndCorners[2] = cv::Point(image.cols, image.rows);
00051 centerAndCorners[3] = cv::Point(0, image.rows);
00052 centerAndCorners[4] = cv::Point(image.cols / 2.0, image.rows / 2.0);
00053
00054 ROS_DEBUG("TARGET IMAGE DIMENSIONS: %d,%d", image.cols, image.rows);
00055
00056 detector.detect(image, keypoints);
00057 extractor.compute(image, keypoints, descriptors);
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 ROS_DEBUG("DESCRIPTORS DIMENSIONS: %d,%d", descriptors.cols, descriptors.rows);
00069 ROS_DEBUG("end Target::init");
00070 ROS_DEBUG("Target: %d keypoints", keypoints.size());
00071 return true;
00072 }
00073
00074
00075 bool Target::detect(cv::Mat cam_descriptors, std::vector< cv::KeyPoint >& cam_keypoints,
00076 std::vector< cv::DMatch >& good_matches, std::vector< int >& idxs_to_remove,
00077 std::vector< cv::Point2f >& target_coord
00078 #ifdef DEBUG_PROJECTION
00079 ,
00080 ucl_drone::Pose3D pose
00081 #endif
00082 #ifdef DEBUG_TARGET
00083 ,
00084 cv::Mat& image_cam
00085 #endif
00086 )
00087 {
00088 ROS_DEBUG("begin Target::detect");
00089
00090
00091 if (cam_descriptors.rows == 0)
00092 {
00093 return false;
00094 }
00095
00096 bool target_detected = false;
00097
00098 std::vector< cv::DMatch > matches;
00099 matcher.match(descriptors, cam_descriptors, matches);
00100
00101
00102 for (int i = 0; i < descriptors.rows; i++)
00103 {
00104
00105 if (matches[i].distance < DIST_THRESHOLD * 0.75)
00106 {
00107 good_matches.push_back(matches[i]);
00108 }
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 ROS_DEBUG("Target::detect matches:%d", good_matches.size());
00121 if (good_matches.size() > this->descriptors.rows / 6.0 && good_matches.size() > 8)
00122 {
00123 target_detected = true;
00124 this->position(cam_keypoints, good_matches, target_coord);
00125
00126 std::vector< cv::Point2f >::const_iterator first = target_coord.begin();
00127 std::vector< cv::Point2f >::const_iterator last = target_coord.begin() + 4;
00128 std::vector< cv::Point2f > contour(first, last);
00129
00130 for (unsigned i = 0; i < cam_keypoints.size(); i++)
00131 {
00132 double result = cv::pointPolygonTest(contour, cam_keypoints[i].pt, false);
00133 if (result >= 0)
00134 {
00135 idxs_to_remove.push_back(i);
00136 }
00137 }
00138 }
00139
00140 std::sort(idxs_to_remove.begin(), idxs_to_remove.end());
00141
00142
00143 int k = 1;
00144 for (int i = 1; i < idxs_to_remove.size(); i++)
00145 {
00146 if (idxs_to_remove[i] != idxs_to_remove[i - 1])
00147 {
00148 idxs_to_remove[k] = idxs_to_remove[i];
00149 k++;
00150 }
00151 }
00152 idxs_to_remove.resize(k);
00153
00154 #ifdef DEBUG_TARGET
00155 cv::Mat img_matches;
00156 cv::drawMatches(image, keypoints, image_cam, cam_keypoints, good_matches, img_matches,
00157 cv::Scalar::all(-1), cv::Scalar::all(-1), std::vector< char >(),
00158 cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
00159 cv::imshow(OPENCV_WINDOW, img_matches);
00160 cv::waitKey(3);
00161 #endif
00162
00163 if (!target_detected)
00164 return false;
00165
00166 #ifdef DEBUG_PROJECTION
00167
00168 ROS_INFO("DEBUG_PROJECTION");
00169 std::vector< cv::Point2f > obj;
00170 std::vector< cv::Point2f > scene;
00171
00172 for (int i = 0; i < good_matches.size(); i++)
00173 {
00174
00175 obj.push_back(keypoints[good_matches[i].queryIdx].pt);
00176 scene.push_back(cam_keypoints[good_matches[i].trainIdx].pt);
00177 }
00178
00179 std::vector< uchar > mask;
00180 cv::Mat H =
00181 cv::findHomography(obj, scene, CV_RANSAC, 2, mask);
00182
00183 std::string rel_error = "\nrelative_error = [";
00184 std::string abs_error = "\nabsolute_error = [";
00185 for (int i = 0; i < good_matches.size(); i++)
00186 {
00187 for (int j = i + 1; j < good_matches.size(); j++)
00188 {
00189 if (mask[i] == 1 && mask[j] == 1)
00190 {
00191 cv::Point2f target_point1 = this->keypoints[good_matches[i].queryIdx].pt;
00192 cv::Point2f target_point2 = this->keypoints[good_matches[j].queryIdx].pt;
00193 double dist1 = cv::norm(target_point1 - target_point2) * 0.274 / 240.0;
00194
00195 if (dist1 > 0.1)
00196 {
00197 std::vector< cv::Point2f > camera_points(2);
00198 camera_points[0] = cam_keypoints[good_matches[i].trainIdx].pt;
00199 camera_points[1] = cam_keypoints[good_matches[j].trainIdx].pt;
00200 std::vector< cv::Point3f > map_points(2);
00201 projection_2D(camera_points, pose, map_points, true);
00202
00203 double dist2 = cv::norm(map_points[0] - map_points[1]);
00204
00205
00206
00207 double relative_error = (dist2 - dist1) / dist1;
00208
00209 double absolute_error = (dist2 - dist1);
00210
00211 rel_error += to_string(relative_error) + ", ";
00212 abs_error += to_string(absolute_error) + ", ";
00213
00214 }
00215 }
00216 }
00217 }
00218 rel_error += "];\n\n";
00219 abs_error += "];\n\n";
00220
00221 printf("%s", rel_error.c_str());
00222 printf("%s", abs_error.c_str());
00223
00224 #endif
00225
00226 ROS_DEBUG("end Target::detect");
00227 return true;
00228 }
00229
00230 void Target::draw(cv::Mat cam_img, std::vector< cv::KeyPoint > cam_keypoints,
00231 std::vector< cv::DMatch > good_matches, cv::Mat& img_matches)
00232 {
00233 cv::drawMatches(image, keypoints, cam_img, cam_keypoints, good_matches, img_matches,
00234 cv::Scalar::all(-1), cv::Scalar::all(-1), std::vector< char >(),
00235 cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
00236
00237
00238 std::vector< cv::Point2f > obj;
00239 std::vector< cv::Point2f > scene;
00240
00241 for (int i = 0; i < good_matches.size(); i++)
00242 {
00243
00244 obj.push_back(keypoints[good_matches[i].queryIdx].pt);
00245 scene.push_back(cam_keypoints[good_matches[i].trainIdx].pt);
00246 }
00247
00248 cv::Mat H = cv::findHomography(obj, scene, CV_RANSAC, 2);
00249
00250
00251 std::vector< cv::Point2f > scene_corners(4);
00252
00253 cv::perspectiveTransform(centerAndCorners, scene_corners, H);
00254
00255
00256 cv::line(img_matches, scene_corners[0] + centerAndCorners[1],
00257 scene_corners[1] + centerAndCorners[1], cv::Scalar(0, 255, 0), 4);
00258 cv::line(img_matches, scene_corners[1] + centerAndCorners[1],
00259 scene_corners[2] + centerAndCorners[1], cv::Scalar(0, 255, 0), 4);
00260 cv::line(img_matches, scene_corners[2] + centerAndCorners[1],
00261 scene_corners[3] + centerAndCorners[1], cv::Scalar(0, 255, 0), 4);
00262 cv::line(img_matches, scene_corners[3] + centerAndCorners[1],
00263 scene_corners[0] + centerAndCorners[1], cv::Scalar(0, 255, 0), 4);
00264
00265 ROS_DEBUG("corner[0] %f %f", scene_corners[0].x, scene_corners[0].y);
00266 ROS_DEBUG("corner[1] %f %f", scene_corners[1].x, scene_corners[1].y);
00267 ROS_DEBUG("corner[2] %f %f", scene_corners[2].x, scene_corners[2].y);
00268 ROS_DEBUG("corner[3] %f %f", scene_corners[3].x, scene_corners[3].y);
00269
00270 ROS_DEBUG("end Target::draw");
00271 }
00272
00273 void Target::position(std::vector< cv::KeyPoint > cam_keypoints,
00274 std::vector< cv::DMatch > good_matches, std::vector< cv::Point2f >& coord)
00275 {
00276
00277 std::vector< cv::Point2f > obj;
00278 std::vector< cv::Point2f > scene;
00279
00280 for (int i = 0; i < good_matches.size(); i++)
00281 {
00282
00283 obj.push_back(keypoints[good_matches[i].queryIdx].pt);
00284 scene.push_back(cam_keypoints[good_matches[i].trainIdx].pt);
00285 }
00286
00287 cv::Mat H = cv::findHomography(obj, scene, CV_RANSAC, 2);
00288
00289
00290 coord.resize(5);
00291
00292 cv::perspectiveTransform(centerAndCorners, coord, H);
00293
00294 ROS_DEBUG("end Target::position");
00295 }
00296
00297 bool customLess(cv::DMatch a, cv::DMatch b)
00298 {
00299 return a.trainIdx < b.trainIdx;
00300 }