Go to the documentation of this file.00001 #include <face_contour_detector/filters/EdgeConnectorGraphBased.h>
00002 #include <string>
00003 #include <face_contour_detector/ImageForest.h>
00004 #include <map>
00005 #include <vector>
00006 #include <opencv/cv.h>
00007 #include <ros/assert.h>
00008
00009 namespace face_contour_detector {
00010
00011 namespace filters {
00012
00013 EdgeConnectorGraphBased::EdgeConnectorGraphBased() {
00014 ResetParameters();
00015 }
00016
00017 std::vector<Parameter> EdgeConnectorGraphBased::GetParameters() {
00018 std::vector<Parameter> re;
00019 std::string name("searchRadius");
00020 re.push_back(Parameter(name, &m_searchRadius, 2, 50));
00021 return re;
00022 }
00023
00024 void EdgeConnectorGraphBased::Apply(const cv::Mat& input, cv::Mat& result) {
00025 ROS_ASSERT(input.channels() == 1);
00026
00027 ImageForest forest(input, 200);
00028 std::map<int, ImageForest::Graph> graphs = forest.GetGraphs();
00029
00030 result = input;
00031
00032 for (int i = 1; i <= forest.NumGraphs(); i++) {
00033 std::vector<ImageForest::Point>::iterator itPoints;
00034 for (itPoints = graphs[i].endPoints.begin(); itPoints != graphs[i].endPoints.end(); itPoints++) {
00035 ImageForest::Point found(-1,-1);
00036 for (int dy = -m_searchRadius; dy <= m_searchRadius; dy++) {
00037 for (int dx = -m_searchRadius; dx <= m_searchRadius; dx++) {
00038 int x = dx + itPoints->x;
00039 int y = dy + itPoints->y;
00040 if (x >= 0 && x < input.cols && y >= 0 && y < input.rows) {
00041 int otherId = forest.GetGraphId(x,y);
00042 if (otherId > i) {
00043 if (found.x == -1 ||
00044 itPoints->Distance(ImageForest::Point(x,y)) < itPoints->Distance(found)) {
00045
00046 found = ImageForest::Point(x,y);
00047 }
00048 }
00049 }
00050 }
00051 }
00052 if (found.x != -1) {
00053 M_Connect(result, itPoints->x, itPoints->y, found.x, found.y);
00054 }
00055 }
00056 }
00057 }
00058
00059 void EdgeConnectorGraphBased::ResetParameters() {
00060 m_searchRadius = 4;
00061 m_connectValue = 255;
00062 }
00063
00064 const std::string& EdgeConnectorGraphBased::GetFilterName() {
00065 return m_filterName;
00066 }
00067
00068 void EdgeConnectorGraphBased::M_Connect(cv::Mat& image, int x1, int y1, int x2, int y2) {
00069 ROS_ASSERT(x1 < image.cols && x1 >= 0);
00070 ROS_ASSERT(x2 < image.cols && x2 >= 0);
00071 ROS_ASSERT(y1 < image.rows && y1 >= 0);
00072 ROS_ASSERT(y2 < image.rows && y2 >= 0);
00073
00074
00075
00076 double dx = x2-x1;
00077 double dy = y2-y1;
00078
00079
00080
00081 if (dx == 0) {
00082 if (dy > 0) {
00083 for (int i = 1; i < dy; i++) {
00084 image.at<unsigned char>(y1+i, x1) = m_connectValue;
00085 }
00086 } else if (dy < 0) {
00087 for (int i = -1; i > dy; i--) {
00088 image.at<unsigned char>(y1+i, x1) = m_connectValue;
00089 }
00090 }
00091 return;
00092 }
00093
00094 if (dy == 0) {
00095 if (dx > 0) {
00096 for (int i = 1; i < dx; i++) {
00097 image.at<unsigned char>(y1, x1+i) = m_connectValue;
00098 }
00099 } else if (dx < 0) {
00100 for (int i = -1; i > dx; i--) {
00101 image.at<unsigned char>(y1, x1+i) = m_connectValue;
00102 }
00103 }
00104 return;
00105 }
00106
00107 if (dx == dy) {
00108 if (dx > 0) {
00109 for (int i = 1; i < dx; i++) {
00110 image.at<unsigned char>(y1+1, x1+i) = m_connectValue;
00111 }
00112 } else if (dx < 0) {
00113 for (int i = -1; i > dx; i--) {
00114 image.at<unsigned char>(y1+1, x1+1) = m_connectValue;
00115 }
00116 }
00117 return;
00118 }
00119
00120
00121
00122
00123 double b = sqrt(dx*dx + dy*dy);
00124 double alpha = acos((b*b + dx*dx - dy*dy)/(2.0*std::abs(b)*std::abs(dx)));
00125 double sinAlpha = sin(alpha);
00126 double sinGamma = sin(M_PI/2.0 - alpha);
00127
00128 if (dx > 0.0) {
00129 for (double currX = double(x1)+0.5; currX < x2; currX += 1.0) {
00130 double currY = (currX-double(x1))*sinAlpha/sinGamma;
00131 if (dy < 0) {
00132 currY *= -1;
00133 }
00134 currY += y1;
00135 ROS_ASSERT(currY >= 0 && currY < image.rows);
00136 image.at<unsigned char>(int(round(currY)), int(ceil(currX))) = m_connectValue;
00137 }
00138 } else if (dx < 0.0) {
00139 for (double currX = double(x1)-0.5; currX > x2; currX -= 1.0) {
00140 double currY = (double(x1)-currX)*sinAlpha/sinGamma;
00141 if (dy < 0) {
00142 currY *= -1.0;
00143 }
00144 currY += y1;
00145 ROS_ASSERT(currY >= 0 && currY < image.rows);
00146 image.at<unsigned char>(int(round(currY)), int(floor(currX))) = m_connectValue;
00147 }
00148 }
00149
00150 if (dy > 0.0) {
00151 for (double currY = double(y1)+0.5; currY < y2; currY += 1.0) {
00152 double currX = (currY-double(y1))*sinGamma/sinAlpha;
00153 if (dx < 0) {
00154 currX *= -1.0;
00155 }
00156 currX += x1;
00157 ROS_ASSERT(currX >= 0 && currX < image.cols);
00158 image.at<unsigned char>(int(ceil(currY)), int(round(currX))) = m_connectValue;
00159 }
00160 } else if (dy < 0.0) {
00161 for (double currY = double(y1)-0.5; currY > y2; currY -= 1.0) {
00162 double currX = (double(y1)-currY)*sinGamma/sinAlpha;
00163 if (dx < 0) {
00164 currX *= -1.0;
00165 }
00166 currX += x1;
00167 ROS_ASSERT(currX >= 0 && currX < image.cols);
00168 image.at<unsigned char>(int(floor(currY)), int(round(currX))) = m_connectValue;
00169 }
00170 }
00171 }
00172
00173
00174 std::string EdgeConnectorGraphBased::m_filterName = std::string("EdgeConnectorGraphBased");
00175 }
00176
00177 }