Go to the documentation of this file.00001 #include <face_contour_detector/filters/RosServices.h>
00002
00003 #include <ros/ros.h>
00004
00005 #include <opencv/cv.h>
00006 #include <opencv/highgui.h>
00007 #include <sensor_msgs/Image.h>
00008 #include <cv_bridge/CvBridge.h>
00009 #include <image_transport/image_transport.h>
00010
00011
00012 #include <face_contour_detector/GetFilters.h>
00013 #include <face_contour_detector/ApplyFilters.h>
00014
00015
00016 #include <face_contour_detector/filters/Filter.h>
00017 #include <face_contour_detector/filters/List.h>
00018
00019
00020 #include <string>
00021 #include <vector>
00022 #include <map>
00023
00024
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027
00028
00029 #include <face_contour_detector/ImageForest.h>
00030
00031 namespace face_contour_detector {
00032
00033 namespace filters {
00034
00035 RosServices::RosServices() {
00036
00037 }
00038 RosServices::~RosServices() {
00039 std::map<std::string, Filter*>::iterator it;
00040 for (it = m_filters.begin(); it != m_filters.end(); it++) {
00041 delete it->second;
00042 }
00043 }
00044 void RosServices::AddFilter(std::string name, Filter* filter) {
00045 m_filters[name] = filter;
00046 }
00047 bool RosServices::HandleApplyRequest(face_contour_detector::ApplyFilters::Request& request, face_contour_detector::ApplyFilters::Response& response) {
00048
00049 response.success = true;
00050 cv::Mat inputImage;
00051
00052 try {
00053
00054 sensor_msgs::CvBridge cvBridge;
00056 if (!cvBridge.fromImage(request.input_image, "mono8")) {
00057 throw sensor_msgs::CvBridgeException("Conversion to OpenCV image failed");
00058 }
00059 ROS_INFO("Image widht=%i height=%i", request.input_image.width, request.input_image.height);
00060
00061 inputImage = cv::Mat(cvBridge.toIpl(), true);
00062
00063 } catch (sensor_msgs::CvBridgeException error) {
00064 ROS_ERROR("could not convert the image with the cvBridge to a cv::Mat");
00065 response.success = false;
00066 return false;
00067 }
00068
00069 int rows = inputImage.rows;
00070 int cols = inputImage.cols;
00071
00072 cv::Mat resultImage(rows, cols, CV_8UC1);
00073
00074
00075
00076
00077 for (int y = 0; y < rows; y++) {
00078 for (int x = 0; x < cols; x++) {
00079 ROS_ASSERT(resultImage.cols > x && resultImage.rows > y);
00080
00081 resultImage.at<unsigned char>(y,x) = 0;
00082 }
00083 }
00084
00085
00086
00087
00088 int areaI = 0;
00089 std::vector<face_contour_detector::filter_area_setup>::iterator areaIt;
00090 for (areaIt = request.areas.begin(); areaIt != request.areas.end(); areaIt++) {
00091
00092
00093
00094
00095 if (areaIt->area.x < 0 || areaIt->area.x >= inputImage.cols ||
00096 areaIt->area.y < 0 || areaIt->area.y >= inputImage.rows ||
00097 areaIt->area.width <= 0 || areaIt->area.height <= 0 ||
00098 areaIt->area.x + areaIt->area.width > inputImage.cols ||
00099 areaIt->area.y + areaIt->area.height > inputImage.rows
00100 ) {
00101 ROS_ERROR("The received area (name=%s, x=%i y=%i width=%i height=%i ) is not valid", areaIt->area.name.c_str(), areaIt->area.x, areaIt->area.y, areaIt->area.width, areaIt->area.height);
00102 response.success = false;
00103 return false;
00104 }
00105
00106
00107 face_contour_detector::filter_area_result areaResponse;
00108 areaResponse.area = areaIt->area;
00109
00110
00111
00112 cv::Mat areaImage(areaIt->area.height, areaIt->area.width, CV_8UC1);
00113
00114 for (int y = 0; y < areaIt->area.height; y++) {
00115 for (int x = 0; x < areaIt->area.width; x++) {
00116 ROS_ASSERT(inputImage.cols > x);
00117 ROS_ASSERT(inputImage.rows > y);
00118 areaImage.at<unsigned char>(y,x) = inputImage.at<unsigned char>(areaIt->area.y + y, areaIt->area.x + x);
00119 }
00120 }
00121
00122
00123 int filterI = 0;
00124
00125 cv::Mat areaImageResult = areaImage.clone();
00126
00127 std::vector<face_contour_detector::filter_setup>::iterator filterIt;
00128 for (filterIt = areaIt->filters.begin(); filterIt != areaIt->filters.end(); filterIt++) {
00129 Filter* currFilter = 0;
00130
00131 if (M_SetupFilter(*filterIt, currFilter)) {
00132
00133 currFilter->Apply(areaImage, areaImageResult);
00134
00135
00136
00137 areaImage = areaImageResult.clone();
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00150
00151
00152
00153 } else {
00154 response.success = false;
00155 return false;
00156 }
00157 filterI++;
00158 }
00159
00160
00161 {
00162 std::vector<face_contour_detector::filter_area_setup>::iterator areaIt2;
00163 bool following = false;
00164 for (areaIt2 = request.areas.begin(); areaIt2 != request.areas.end(); areaIt2++) {
00165 if (following) {
00166 for (int y = 0; y < areaIt2->area.height; y++) {
00167 for (int x = 0; x < areaIt2->area.width; x++) {
00168 int realX = areaIt2->area.x + x - areaIt->area.x;
00169 int realY = areaIt2->area.y + y - areaIt->area.y;
00170 if (realX >= 0 && realX < areaIt->area.width &&
00171 realY >= 0 && realY < areaIt->area.height) {
00172 ROS_ASSERT(areaImageResult.rows > realY && areaImageResult.cols > realX);
00173 areaImageResult.at<unsigned char>(realY,realX) = (unsigned char)0;
00174 }
00175 }
00176 }
00177 } else if (areaIt2 == areaIt) {
00178 following = true;
00179 }
00180 }
00181 }
00182
00183
00184 M_ExtractProperties(areaImageResult, areaResponse.result_properties);
00185 response.area_results.push_back(areaResponse);
00186
00187
00188 for (int y = 0; y < areaIt->area.height; y++) {
00189 for (int x = 0; x < areaIt->area.width; x++) {
00190 ROS_ASSERT(areaIt->area.y + y >= 0 && areaIt->area.y + y < resultImage.rows);
00191 ROS_ASSERT(areaIt->area.x + x >= 0 && areaIt->area.x + x < resultImage.cols);
00192 resultImage.at<unsigned char>(areaIt->area.y + y, areaIt->area.x + x) = (unsigned char)areaImageResult.at<unsigned char>(y, x);
00193 }
00194 }
00195
00196 areaI++;
00197 }
00198
00199
00200 M_ExtractProperties(resultImage, response.result_properties);
00201
00202
00203 try {
00204
00205 sensor_msgs::CvBridge cvBridge;
00206
00207 IplImage ipl = resultImage;
00208 response.result_image = *(cvBridge.cvToImgMsg(&ipl));
00209 } catch (sensor_msgs::CvBridgeException error) {
00210 ROS_ERROR("could not convert the image with the cvBridge to a sensor_msgs/Image");
00211 response.success = false;
00212 return false;
00213 }
00214 return true;
00215 }
00216 bool RosServices::HandleGetRequest(face_contour_detector::GetFilters::Request& request, face_contour_detector::GetFilters::Response& response) {
00217
00218 std::map<std::string, Filter*>::iterator it;
00219 for (it = m_filters.begin(); it != m_filters.end(); it++) {
00220 face_contour_detector::filter f;
00221 f.name = it->first;
00222 std::vector<Parameter> params = it->second->GetParameters();
00223 std::vector<Parameter>::iterator paramIt;
00224 for (paramIt = params.begin(); paramIt != params.end(); paramIt++) {
00225 face_contour_detector::parameter p;
00226 p.name = paramIt->GetName();
00227 if (paramIt->GetType() == face_contour_detector::filters::TBOOL) {
00228 p.type = "bool";
00229 } else if (paramIt->GetType() == face_contour_detector::filters::TINT) {
00230 p.type = "int";
00231 } else if (paramIt->GetType() == face_contour_detector::filters::TDOUBLE) {
00232 p.type = "float";
00233 } else if (paramIt->GetType() == face_contour_detector::filters::TSTRING) {
00234 p.type = "string";
00235 }
00236 p.ruler_minimum = paramIt->GetRulerMinimum();
00237 p.ruler_maximum = paramIt->GetRulerMaximum();
00238 f.parameters.push_back(p);
00239 }
00240 response.filters.push_back(f);
00241 }
00242 return true;
00243 }
00244
00245 void RosServices::M_ExtractProperties(cv::Mat& image, std::vector<face_contour_detector::name_value_pair>& result) {
00246
00247 ROS_ASSERT(image.channels() == 1);
00248
00249
00250 face_contour_detector::ImageForest forest(image, 200);
00251 std::map<int, face_contour_detector::ImageForest::Graph> graphs = forest.GetGraphs();
00252
00253
00254 {
00255 face_contour_detector::name_value_pair entry;
00256 std::stringstream valuestream;
00257 entry.type = "int";
00258 entry.name = "numGraphs";
00259 valuestream<<graphs.size();
00260 entry.value = valuestream.str().c_str();
00261 result.push_back(entry);
00262 }
00263
00264
00265 {
00266 face_contour_detector::name_value_pair entry;
00267 std::stringstream valuestream;
00268 int count = 0;
00269 std::map<int, face_contour_detector::ImageForest::Graph>::iterator it;
00270 for (it = graphs.begin(); it != graphs.end(); it++) {
00271 count += it->second.connectingPoints.size();
00272 }
00273 entry.type = "int";
00274 entry.name = "numGraphConnectingPoints";
00275 valuestream<<count;
00276 entry.value = valuestream.str().c_str();
00277 result.push_back(entry);
00278 }
00279
00280
00281 {
00282 face_contour_detector::name_value_pair entry;
00283 std::stringstream valuestream;
00284 int count = 0;
00285 std::map<int, face_contour_detector::ImageForest::Graph>::iterator it;
00286 for (it = graphs.begin(); it != graphs.end(); it++) {
00287 count += it->second.endPoints.size();
00288 }
00289 entry.type = "int";
00290 entry.name = "numGraphEndpoints";
00291 valuestream<<count;
00292 entry.value = valuestream.str().c_str();
00293 result.push_back(entry);
00294 }
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 {
00309 face_contour_detector::name_value_pair entry;
00310 std::stringstream valuestream;
00311 entry.type = "float";
00312 entry.name = "graphmass";
00313 double graphMass = forest.CallculateGraphMass();
00314 valuestream<<graphMass;
00315 entry.value = valuestream.str().c_str();
00316 result.push_back(entry);
00317 }
00318 }
00319
00320 bool RosServices::M_SetupFilter(face_contour_detector::filter_setup& filterSetup, Filter*& filter) {
00321
00322 if (m_filters.find(filterSetup.name) == m_filters.end()) {
00323 ROS_ERROR("Could not find a filter with the name \"%s\"", filterSetup.name.c_str());
00324 return false;
00325 }
00326 filter = m_filters[filterSetup.name];
00327
00328
00329 filter->ResetParameters();
00330 std::vector<Parameter> params = filter->GetParameters();
00331 std::vector<Parameter>::iterator it;
00332 for (it = params.begin(); it != params.end(); it++) {
00333 std::vector<face_contour_detector::name_value_pair>::iterator found = filterSetup.parameters.end();
00334 std::vector<face_contour_detector::name_value_pair>::iterator nvIt;
00335 for (nvIt = filterSetup.parameters.begin(); nvIt != filterSetup.parameters.end(); nvIt++) {
00336 if (nvIt->name == it->GetName()) {
00337 found = nvIt;
00338 break;
00339 }
00340 }
00341 if (found != filterSetup.parameters.end()) {
00342 if (it->GetType() == face_contour_detector::filters::TBOOL) {
00343 *(it->GetBoolValuePtr()) = (found->value == std::string("1") || found->value == std::string("true"));
00344 } else if (it->GetType() == face_contour_detector::filters::TINT) {
00345 *(it->GetIntValuePtr()) = atoi(found->value.c_str());
00346 } else if (it->GetType() == face_contour_detector::filters::TDOUBLE) {
00347 *(it->GetDoubleValuePtr()) = atof(found->value.c_str());
00348 } else if (it->GetType() == face_contour_detector::filters::TSTRING) {
00349 *(it->GetStringValuePtr()) = found->value;
00350 }
00351 } else {
00352 ROS_WARN("Could not find the parameter \"%s\" for the filter \"%s\"", it->GetName().c_str(), filterSetup.name.c_str());
00353 }
00354 }
00355 return true;
00356 }
00357
00358 }
00359
00360 }