RosServices.cpp
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 //service definitions
00012 #include <face_contour_detector/GetFilters.h>
00013 #include <face_contour_detector/ApplyFilters.h>
00014 
00015 //filters
00016 #include <face_contour_detector/filters/Filter.h>
00017 #include <face_contour_detector/filters/List.h>
00018 
00019 //std
00020 #include <string>
00021 #include <vector>
00022 #include <map>
00023 
00024 //for atoi and atof
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 
00028 //forest
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         //extract image
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             //inputImage.create(request.input_image.height, request.input_image.width, CV_8UC1);
00061             inputImage = cv::Mat(cvBridge.toIpl(), true);
00062             //cv::imwrite("filter_services_req_in.png", inputImage);
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         //cv::imwrite("filter_services_req_in_aftercreateresult.png", inputImage);
00075         
00076         //Don't use copyTo BECAUSE IT IS BUGGED LIKE HELL (ok maybe it is not)
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                 //resultImage.at<unsigned char>(y,x) = inputImage.at<unsigned char>(y,x);
00081                 resultImage.at<unsigned char>(y,x) = 0;
00082             }
00083         }
00084         //cv::imwrite("filter_services_req_in_aftercopy.png", inputImage);
00085         
00086         //iteratore through the areas
00087         //ROS_INFO("Starting to iterate through the areas");
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                 //ROS_INFO("at area %i name=%s x=%i y=%i width=%i height=%i", areaI, areaIt->area.name.c_str(), areaIt->area.x, areaIt->area.y, areaIt->area.width, areaIt->area.height);
00093 
00094             //check if the area is valid
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             //generate area response message
00107             face_contour_detector::filter_area_result areaResponse;
00108             areaResponse.area = areaIt->area;
00109             
00110             //copy out the area
00111             //ROS_INFO("copying out area");
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             //run the filters
00123             int filterI = 0;
00124             //ROS_INFO("copying out area to result cv::Mat");
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                 //ROS_INFO("starting filter setup");
00131                 if (M_SetupFilter(*filterIt, currFilter)) {
00132                         //ROS_INFO("applying filter");
00133                     currFilter->Apply(areaImage, areaImageResult);
00134                     //ROS_INFO("copy result");
00135                     //DONT USE COPY TO IT IS FUCKING BUGGED
00136                     //areaImageResult.copyTo(areaImage);
00137                     areaImage = areaImageResult.clone();
00138                     /*for (int y = 0; y < areaImageResult.rows; y++) {
00139                         for (int x = 0; x < areaImageResult.cols; x++) {
00140                             ROS_ASSERT(y < areaImage.rows);
00141                             ROS_ASSERT(x < areaImage.cols);
00142                             //ROS_INFO("Reading");
00143                             unsigned char data = areaImageResult.at<unsigned char>(y, x);
00144                             //ROS_INFO("Writing");
00145                             areaImage.at<unsigned char>(y,x) =  data;
00146                         }
00147                     }*/
00148                     
00150                     //std::stringstream s;
00151                     //s<<"ros_filter_service_debug_a"<<areaI<<"_f"<<filterI<<".png";
00152                     //cv::imwrite(s.str().c_str(), areaImage);
00153                 } else  {
00154                     response.success = false;
00155                     return false;
00156                 }
00157                 filterI++;
00158             }
00159             
00160             //overwrite following areas
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             //read out the result properties for this area and push it onto the stack
00184             M_ExtractProperties(areaImageResult, areaResponse.result_properties);
00185             response.area_results.push_back(areaResponse);
00186             
00187             //paste the result into the bigger resultpicture
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         //Extract the properties for the hole image
00200         M_ExtractProperties(resultImage, response.result_properties);
00201         
00202         //Putting the result image into the response
00203         try {
00204             
00205             sensor_msgs::CvBridge cvBridge;
00206             //cv::imwrite("filter_services_req_out.bmp", resultImage);
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         //creating forest out of image
00250         face_contour_detector::ImageForest forest(image, 200);
00251         std::map<int, face_contour_detector::ImageForest::Graph> graphs = forest.GetGraphs();
00252         
00253         //num of graphs
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         //num of connectingpoints
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         //num of endpoints
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         //edgyness
00297         /*{
00298             face_contour_detector::name_value_pair entry;
00299             std::stringstream valuestream;
00300             entry.type = "float";
00301             entry.name = "graphEdgyness";
00302             valuestream<<forest.CallculateEdgyness();
00303             entry.value = valuestream.str().c_str();
00304             result.push_back(entry);
00305         }*/
00306         
00307         //black to whitepixel ratio (num blackpixels/num whitepixels)
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         //get the filter
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         //setup the parameters
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 } //namespace filters
00359 
00360 } //namespace face_contour_detector
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends


face_contour_detector
Author(s): Fabian Wenzelmann and Julian Schmid
autogenerated on Wed Dec 26 2012 16:18:17