| 180 | } |
| 181 | |
| 182 | cv::Vec4f Extractor::getSymmetryAxis(const std::vector<cv::Point2f>& points) |
| 183 | { |
| 184 | #if 0 |
| 185 | // right eye index 42, left eye index 48. |
| 186 | // Make sure that right eye is one the right side. (no pun intended) |
| 187 | assert(points[48].x - points[42].x > 1/* pixel */); |
| 188 | |
| 189 | cv::Point2f middle = (points[48] + points[42].x)/2; |
| 190 | cv::Vec4f line; // (vx, vy, x0, y0) where (vx, vy) is a normalized vector collinear to the line and (x0, y0) is a point on the line. |
| 191 | line[2] = middle.x; |
| 192 | line[3] = middle.y; |
| 193 | |
| 194 | float k = (points[48].y - points[42].y) / (points[48].x - points[42].x); |
| 195 | |
| 196 | // atan(x) return angle in [-pi/2, pi/2], while atan2(y, x) return angle in [-pi, pi]. |
| 197 | // But we know that our x > 0, we can use atan directly. |
| 198 | float theta = std::atan(k); |
| 199 | line[0] = std::cos(theta); |
| 200 | line[1] = std::sin(theta); |
| 201 | #else |
| 202 | |
| 203 | // those points are one the vertical line. |
| 204 | std::vector<cv::Point2f> points_on_line; |
| 205 | points_on_line.push_back(points[16]); |
| 206 | points_on_line.push_back(points[ 6]); |
| 207 | |
| 208 | // right 15 14 13 12 11 10 9 8 7 |
| 209 | // left 17 18 19 0 1 2 3 4 5 |
| 210 | // (right + left)/2 are approximately on the line |
| 211 | for(int i = 15, j = 17; i >= 7; --i, j = (j+1)%20) |
| 212 | points_on_line.push_back((points[i] + points[j])/2); |
| 213 | |
| 214 | // eye brow |
| 215 | for(int i = 20; i <= 24; ++i) |
| 216 | points_on_line.push_back((points[i] + points[i + 7])/2); |
| 217 | |
| 218 | // eye, currently STASM doesn't detect left eyes precisely. |
| 219 | // besides, iris is not fixed in center, not suitable for computing. |
| 220 | /* |
| 221 | for(int i = 34; i <= 41; ++i) |
| 222 | points_on_line.push_back((points[i] + points[i + 10])/2); |
| 223 | points_on_line.push_back((points[42] + points[43])/2); |
| 224 | */ |
| 225 | // nose |
| 226 | points_on_line.push_back(points[53]); |
| 227 | points_on_line.push_back((points[52] + points[54])/2); |
| 228 | points_on_line.push_back(points[56]); |
| 229 | points_on_line.push_back((points[62] + points[58])/2); |
| 230 | points_on_line.push_back((points[55] + points[57])/2); |
| 231 | points_on_line.push_back((points[61] + points[59])/2); |
| 232 | points_on_line.push_back(points[60]); |
| 233 | |
| 234 | // mouth |
| 235 | // mouth can varies a lot with respect to different expressions, so overlook lower lip. |
| 236 | points_on_line.push_back(points[66]); |
| 237 | points_on_line.push_back(points[71]); |
| 238 | points_on_line.push_back((points[65] + points[67])/2); |
| 239 | points_on_line.push_back((points[64] + points[68])/2); |
nothing calls this directly
no outgoing calls
no test coverage detected