Go to the documentation of this file.00001 #include <face_contour_detector/FaceContourRequestHandler.h>
00002
00003
00004 #include <opencv/cv.h>
00005 #include <opencv/highgui.h>
00006 #include <sensor_msgs/Image.h>
00007 #include <cv_bridge/CvBridge.h>
00008 #include <image_transport/image_transport.h>
00009
00010
00011 #include <face_contour_detector/GetFilters.h>
00012 #include <face_contour_detector/ApplyFilters.h>
00013 #include <face_contour_detector/autoselect_result.h>
00014 #include <face_contour_detector/ContourDetectorGUI.h>
00015 #include <face_contour_detector/experience_request.h>
00016 #include <face_contour_detector/filters/MaskBlur.h>
00017
00018 #include <portrait_robot_msgs/alubsc_node_instr.h>
00019 #include <portrait_robot_msgs/alubsc_status_msg.h>
00020
00021
00022 #include <tinyxml/tinyxml.h>
00023
00024
00025 #include <face_contour_detector/AutoParameterExplorer.h>
00026 #include <boost/function.hpp>
00027 #include <face_contour_detector/AreaParameterChooserWorker.h>
00028
00029 namespace face_contour_detector {
00030
00031 FaceContourRequestHandler::FaceContourRequestHandler(ros::NodeHandle& node,
00032 std::string exploreConfigPath) :
00033 node(node), exploreConfigPath(exploreConfigPath) {
00034 }
00035 FaceContourRequestHandler::~FaceContourRequestHandler() {
00036 while (!requests.empty()) {
00037 delete requests.front().image;
00038 delete requests.front().mask;
00039 requests.pop();
00040 }
00041 }
00042
00043 void FaceContourRequestHandler::SolveOneRequest() {
00044 if (!requests.empty()) {
00045
00046
00047 cv::Mat* currentImg = requests.front().image;
00048 cv::Mat* currentMask = requests.front().mask;
00049
00050 requests.pop();
00051
00052 M_SendStatusMessage("Blurring around masked areas");
00053
00054
00055 cv::Mat* maskedImage = new cv::Mat(currentImg->rows, currentImg->cols,
00056 CV_8UC3);
00057 {
00058
00059 face_contour_detector::Bgr8 clearcolor;
00060 clearcolor.b = 255;
00061 clearcolor.g = 255;
00062 clearcolor.r = 255;
00063 face_contour_detector::filters::MaskBlur mb =
00064 face_contour_detector::filters::MaskBlur(10, clearcolor);
00065
00066 cv::Mat bwMask = cv::Mat(currentMask->rows, currentMask->cols,
00067 CV_8UC1);
00068 cv::cvtColor(*currentMask, bwMask, CV_BGR2GRAY);
00069 mb.SetMask(bwMask, 0, 255);
00070
00071 mb.Apply(*currentImg, *maskedImage);
00072
00073 delete currentImg;
00074 currentImg = maskedImage;
00075 cv::imwrite("parameter_autoselect_bluredImage.png", *currentImg);
00076 }
00077
00078 M_SendStatusMessage("starting exploration for good parameters...");
00079
00080
00081 std::vector<face_contour_detector::autoselect_result> result;
00082
00083
00084 std::vector<WorkerSetting> settings;
00085 M_LoadExploreSettings(settings);
00086
00087 std::vector<WorkerSetting>::iterator setIt;
00088 int i = 1;
00089 for (setIt = settings.begin(); setIt != settings.end(); setIt++) {
00090 face_contour_detector::AreaParameterChooserWorker worker(node,
00091 *currentImg, *currentMask, setIt->targetValues);
00092 worker.CallculateParameters(setIt->numResults, setIt->steps,
00093 result);
00094
00095 if (result.size() < setIt->numResults) {
00096 ROS_ERROR("did not get enough results for the request");
00097 M_SendStatusMessage(
00098 "did not get enough results for the request, please try to send a better image");
00099 delete currentImg;
00100 delete currentMask;
00101 return;
00102 } else {
00103 std::stringstream sstr;
00104 sstr << "found " << result.size()
00105 << " parameter combination(s) by exploring with worker "
00106 << i;
00107 M_SendStatusMessage(sstr.str());
00108 }
00109 i++;
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 M_SendStatusMessage(
00123 "try to find parameters by searching rated results...");
00124
00125
00126 ros::ServiceClient exprClient = node.serviceClient<
00127 face_contour_detector::experience_request>(
00128 "experience_autoselector");
00129 face_contour_detector::experience_request exprSrv;
00130
00131 cv::Mat imgCopy = currentImg->clone();
00132 cv::Mat maskCopy = currentMask->clone();
00133
00134 try {
00135 sensor_msgs::CvBridge cvBridge;
00136 IplImage ipl = imgCopy;
00137 exprSrv.request.image = *(cvBridge.cvToImgMsg(&ipl));
00138
00139 } catch (sensor_msgs::CvBridgeException& error) {
00140 ROS_ERROR(
00141 "could not convert the image with the cvBridge to a sensor_msgs/Image");
00142 return;
00143 }
00144
00145 try {
00146 sensor_msgs::CvBridge cvBridge;
00147 IplImage ipl = maskCopy;
00148 exprSrv.request.mask = *(cvBridge.cvToImgMsg(&ipl));
00149
00150 } catch (sensor_msgs::CvBridgeException& error) {
00151 ROS_ERROR(
00152 "could not convert the image with the cvBridge to a sensor_msgs/Image");
00153 return;
00154 }
00155
00156 if (exprClient.call(exprSrv)) {
00157 std::vector<face_contour_detector::autoselect_result>::iterator it;
00158 for (it = exprSrv.response.proposals.begin();
00159 it != exprSrv.response.proposals.end(); it++) {
00160 result.push_back(*it);
00161 }
00162 M_SendStatusMessage(
00163 "received experience based parameter combinations");
00164 } else {
00165 ROS_WARN(
00166 "Could not reach the experience based autoparameter chooser");
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 std::string topic = "display_on_gui";
00186 ros::ServiceClient client = node.serviceClient<
00187 face_contour_detector::ContourDetectorGUI>(topic);
00188 face_contour_detector::ContourDetectorGUI srv;
00189 srv.request.proposals = result;
00190 ROS_INFO("gui service request send");
00191 M_SendStatusMessage("opening gui...");
00192 if (client.call(srv)) {
00193 ROS_INFO("gui respondet");
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 } else {
00208 ROS_ERROR("Failed to call service %s", topic.c_str());
00209 }
00210 M_SendStatusMessage("done");
00211
00212
00213
00214
00215
00216
00217
00218
00219 delete currentImg;
00220 delete currentMask;
00221
00222 ROS_INFO("solved a request");
00223 }
00224 }
00225
00226 bool FaceContourRequestHandler::HandleAlubscRequest(
00227 portrait_robot_msgs::alubsc_node_instr::Request &req,
00228 portrait_robot_msgs::alubsc_node_instr::Response &res) {
00229 if (req.abort) {
00231 M_SendStatusMessage("received abort");
00232 } else {
00233 std::vector<sensor_msgs::Image>::const_iterator it;
00234 ImageMaskPair p;
00235 p.image = 0;
00236 p.mask = 0;
00237 int i = 0;
00238 for (it = req.images.begin(); it != req.images.end(); it++) {
00239 if (i > 1) {
00240 ROS_ERROR("More than two images in the message");
00241 res.success = false;
00242 return false;
00243 }
00244 try {
00245
00246 sensor_msgs::CvBridge cvBridge;
00248 if (!cvBridge.fromImage(*it, "bgr8"))
00249 throw sensor_msgs::CvBridgeException(
00250 "Conversion to OpenCV image failed");
00251 ;ROS_INFO(
00252 "got image with widht=%i and height=%i", it->width, it->height);
00253 if (i == 0) {
00254 p.image = new cv::Mat(cvBridge.toIpl(), true);
00255 } else if (i == 1) {
00256 p.mask = new cv::Mat(cvBridge.toIpl(), true);
00257 }
00258
00259 } catch (sensor_msgs::CvBridgeException& error) {
00260 ROS_ERROR(
00261 "could not convert the image with the cvBridge to a cv::Mat");
00262 res.success = false;
00263 return false;
00264 }
00265 i++;
00266 }
00267 if (p.image == 0) {
00268 ROS_ERROR("no image received");
00269 res.success = false;
00270 return false;
00271 }
00272 if (p.mask == 0) {
00273 ROS_ERROR("no mask received");
00274 res.success = false;
00275 return false;
00276 }
00277 requests.push(p);
00278 res.success = true;
00279 }
00280 return true;
00281 }
00282
00283 void FaceContourRequestHandler::M_SendStatusMessage(
00284 const std::string& message) {
00285 ros::ServiceClient client = node.serviceClient<
00286 portrait_robot_msgs::alubsc_status_msg>("status_msg");
00287 portrait_robot_msgs::alubsc_status_msg srv;
00288 srv.request.ID = 2;
00289 srv.request.message = message;
00290 if (!client.call(srv)) {
00291 ROS_WARN(
00292 "could not reach status message service \"%s\"", client.getService().c_str());
00293 ROS_INFO("%s", message.c_str());
00294 }
00295 }
00296
00297 void FaceContourRequestHandler::M_LoadExploreSettings(
00298 std::vector<WorkerSetting>& settings) {
00299 TiXmlDocument doc(exploreConfigPath.c_str());
00300 if (!doc.LoadFile()) {
00301 ROS_ERROR("Could not load the explore_settings xml config file");
00302 M_SendStatusMessage(
00303 "Could not load the explore_settings xml config file");
00304 return;
00305 }
00306 TiXmlElement* root = doc.RootElement();
00307 for (TiXmlElement* worker = root->FirstChildElement("worker"); worker;
00308 worker = worker->NextSiblingElement("worker")) {
00309
00310 WorkerSetting setting;
00311 if (worker->Attribute("steps")) {
00312 setting.steps = atoi(worker->Attribute("steps"));
00313 } else {
00314 setting.steps = 15;
00315 }
00316 if (worker->Attribute("numresults")) {
00317 setting.numResults = atoi(worker->Attribute("numresults"));
00318 } else {
00319 setting.numResults = 2;
00320 }
00321 for (TiXmlElement* area = worker->FirstChildElement("area"); area;
00322 area = area->NextSiblingElement("area")) {
00323 if (area->Attribute("name")) {
00324 setting.targetValues[area->Attribute("name")] = std::map<
00325 std::string, double>();
00326 for (TiXmlElement* targetValue = area->FirstChildElement(
00327 "target_value");
00328 targetValue;
00329 targetValue = targetValue->NextSiblingElement(
00330 "target_value")) {
00331 if (targetValue->Attribute("name")
00332 && targetValue->Attribute("value")) {
00333 setting.targetValues[area->Attribute("name")][targetValue->Attribute(
00334 "name")] = atof(
00335 targetValue->Attribute("value"));
00336 }
00337 }
00338 }
00339 }
00340 settings.push_back(setting);
00341 }
00342 }
00343
00344 }