68 m_bInitialized =
false;
70 if (objRects.size() < 1)
73 m_ObjRect = objRects[0];
75 float wdiff = (objRects[0].width / 3.0f);
76 float hdiff = (objRects[0].height / 10.0f);
77 float woff = objRects[0].width - (wdiff * 2.0f);
78 float hoff = objRects[0].height - (hdiff * 8.0f);
79 m_ObjRect.width = (int)wdiff * 2;
80 m_ObjRect.height = (int)hdiff * 8;
81 m_ObjRect.x = objRects[0].x + ((int)woff / 2);
82 m_ObjRect.y = objRects[0].y + ((int)hoff / 2);
84 image.copyTo(m_image);
85 m_image = m_image(m_ObjRect);
88 int patchSize = m_image.cols / 6;
92 m_pcorners.push_back(cv::Point2f((
float)m_ObjRect.x, (
float)m_ObjRect.y));
93 m_pcorners.push_back(cv::Point2f((
float)m_ObjRect.x + m_ObjRect.width, (
float)m_ObjRect.y));
94 m_pcorners.push_back(cv::Point2f((
float)m_ObjRect.x + m_ObjRect.width, (
float)m_ObjRect.y + m_ObjRect.height));
95 m_pcorners.push_back(cv::Point2f((
float)m_ObjRect.x, (
float)m_ObjRect.y + m_ObjRect.height));
98 for (
unsigned int i = 0; i < m_pcorners.size(); i++)
99 this->push_back(cv::Point2f(m_pcorners[i].x, m_pcorners[i].y));
101 cv::Mat dmask = cv::Mat(image.rows, image.cols, CV_8UC1);
103 for (
unsigned int i = 1; i < objRects.size(); i++)
105 cv::Rect orect = objRects[i];
108 orect.x += objRects[0].x;
109 orect.y += objRects[0].y;
111 cv::rectangle(dmask, orect, cv::Scalar(255), cv::FILLED);
114 cv::Size subPixWinSize(5, 5);
115 cv::TermCriteria termcrit(cv::TermCriteria::MAX_ITER | cv::TermCriteria::EPS, 30, 0.03f);
119 cv::goodFeaturesToTrack(image, m_ObjPoints, m_maxFeatures, 0.01, 2, dmask, 3,
false, 0.03f);
143 m_prevFramePoints = m_ObjPoints;
144 m_lastFoundPoints.resize(m_ObjPoints.size(),
true);
147#ifdef DEBUG_FACE_TRACKING
149 m_image.copyTo(mdebug);
150 cv::cvtColor(mdebug, mdebug, CV_GRAY2BGR);
152 for (
int i = 0; i < (int)m_ObjPoints.size(); i++)
154 cv::circle(mdebug, m_ObjPoints[i] - cv::Point2f((
float)m_ObjRect.x, (
float)m_ObjRect.y), 2, cv::Scalar(0, 0, 255), 1);
157 int xoff = (objRects[0].width - m_ObjRect.width) / 2;
158 int yoff = (objRects[0].height - m_ObjRect.height) / 2;
159 for (
unsigned int i = 1; i < objRects.size(); i++)
161 cv::Rect orect = objRects[i];
164 cv::rectangle(mdebug, orect, cv::Scalar(255, 0, 0), 1);
166 cv::imshow(
"Face Reference", mdebug);
169 catch(std::exception& e)
171 MMechostr(MSKRUNTIME,
"AR marker could not detect enough features points : %s", e.what());
175 if (m_ObjPoints.size() > m_minInliners)
176 m_bInitialized =
true;
178 m_bInitialized =
true;
200 std::vector<uchar> status;
201 std::vector<float> err;
202 cv::Size subPixWinSize(20, 20);
203 cv::TermCriteria termcrit(cv::TermCriteria::MAX_ITER | cv::TermCriteria::EPS, 20, 0.03);
208#ifdef DEBUG_FACE_TRACKING
210 frame.copyTo(mdebug);
211 cv::cvtColor(mdebug, mdebug, CV_GRAY2BGR);
214 cv::buildOpticalFlowPyramid(frame, m_nextPyr, subPixWinSize, 3,
true);
216 if (m_ObjPoints.empty() || m_prevPyr.empty())
218 m_prevPyr.swap(m_nextPyr);
222 std::vector<cv::Point2f> nFramePoints;
223 std::vector<cv::Point2f> nGoodFramePoints;
224 std::vector<cv::Point2f> nGoodPoints;
225 std::vector<cv::Mat> nGoodPatches;
226 unsigned int goodtracks = 0;
229 cv::calcOpticalFlowPyrLK(m_prevPyr, m_nextPyr, m_prevFramePoints, nFramePoints, status, err, subPixWinSize, 3, termcrit, cv::OPTFLOW_FARNEBACK_GAUSSIAN, 0.001f);
232 unsigned int nbMatches = 0;
233 for (
unsigned int i = 0; i < nFramePoints.size(); ++i)
237 movept += cv::norm(nFramePoints[i] - m_prevFramePoints[i]);
243 double threshold = 0.6;
244 for (
unsigned int i = 0; i < m_ObjPoints.size(); i++)
246 double dist = abs(cv::norm(nFramePoints[i] - m_prevFramePoints[i]));
248 if (status[i] == 1 && err[i] <= 16.0 && (dist < 0.5 || dist < abs(movept * 2.0)))
251 nGoodPoints.push_back(m_ObjPoints[i]);
252 nGoodFramePoints.push_back(nFramePoints[i]);
253 m_prevFramePoints[i] = nFramePoints[i];
254 m_lastFoundPoints[i] =
true;
256#ifdef DEBUG_FACE_TRACKING
257 cv::circle(mdebug, nFramePoints[i], 2, cv::Scalar(0, 255, 0), 1);
262 m_lastFoundPoints[i] =
false;
263 m_prevFramePoints[i] = m_prevFramePoints[i];
265#ifdef DEBUG_FACE_TRACKING
266 cv::circle(mdebug, m_prevFramePoints[i], 4, cv::Scalar(0, 0, 255), 2);
271 catch(std::exception &e)
273 std::string mess = e.what();
274 m_bInitialized =
false;
276 m_prevFramePoints.clear();
281 m_prevPyr.swap(m_nextPyr);
282 frame.copyTo(m_prevFrame);
284 if (m_initFrames < m_nbInitFrames)
286 m_ObjPoints = nGoodPoints;
287 m_prevFramePoints = nGoodFramePoints;
291 if ((goodtracks < m_minInliners) || !
GetCorners(nGoodPoints, nGoodFramePoints))
293 m_bInitialized =
false;
295 m_prevFramePoints.clear();
297 m_PosSmoothers.
Reset();
302#ifdef DEBUG_FACE_TRACKING
303 cv::Scalar color(255, 0, 0);
306 cv::line(mdebug, this->at(0), this->at(1), color, lineWidth, CV_AA);
307 cv::line(mdebug, this->at(1), this->at(2), color, lineWidth, CV_AA);
308 cv::line(mdebug, this->at(2), this->at(3), color, lineWidth, CV_AA);
309 cv::line(mdebug, this->at(3), this->at(0), color, lineWidth, CV_AA);
310 cv::rectangle(mdebug, this->at(0)-cv::Point2f(2,2), this->at(0)+cv::Point2f(2,2), cv::Scalar(0,0,255), lineWidth, CV_AA);
311 cv::rectangle(mdebug, this->at(1)-cv::Point2f(2,2), this->at(1)+cv::Point2f(2,2), cv::Scalar(0,255,0), lineWidth, CV_AA);
312 cv::rectangle(mdebug, this->at(2)-cv::Point2f(2,2), this->at(2)+cv::Point2f(2,2), cv::Scalar(255,0,0), lineWidth, CV_AA);
316 cv::minEnclosingCircle(nGoodFramePoints, mcenter, mradius);
318 cv::circle(mdebug, mcenter, (
int)mradius, cv::Scalar(0,255,0));
319 cv::imshow(
"Face Tracking", mdebug);
581 bool found = (
detectFeatured(frame, color, camparam.CamSize)) ?
true :
false;
582 m_bInitialized = found;
586 double modelview_matrix[16];
593 cv::Mat R(3, 3, CV_32F);
596 float angleRad = CV_PI / 2.0f;
610 cv::Mat RZ = cv::Mat::eye(3, 3, CV_32F);
611 RZ.at<
float>(0, 0) = cos(angleRad);
612 RZ.at<
float>(0, 1) = -sin(angleRad);
613 RZ.at<
float>(1, 0) = sin(angleRad);
614 RZ.at<
float>(1, 1) = cos(angleRad);
620 cv::Rodrigues(R, Rvec);
622 glGetModelViewMatrix(modelview_matrix);
624 catch (std::exception&)
636 Vector3 pixelPosition(0.0, 0.0, 0.0);
637 for (
int j = 0; j<4; j++)
639 pixelPosition.
x += (*this).at(j).x;
640 pixelPosition.
y += (*this).at(j).y;
643 pixelPosition.
z = sqrt(pow(((*this).at(1).x - (*this).at(0).x), 2) + pow(((*this).at(1).y - (*this).at(0).y), 2));
644 pixelPosition.
z += sqrt(pow(((*this).at(2).x - (*this).at(1).x), 2) + pow(((*this).at(2).y - (*this).at(1).y), 2));
645 pixelPosition.
z += sqrt(pow(((*this).at(3).x - (*this).at(2).x), 2) + pow(((*this).at(3).y - (*this).at(2).y), 2));
646 pixelPosition.
z += sqrt(pow(((*this).at(0).x - (*this).at(3).x), 2) + pow(((*this).at(0).y - (*this).at(3).y), 2));
648 pixelPosition.
x /= 4.;
649 pixelPosition.
y /= 4.;
650 pixelPosition.
z /= 4.;
656 SetPosition(
Vector3(
static_cast<float>(reverse ? -modelview_matrix[12] : modelview_matrix[12]),
static_cast<float>(modelview_matrix[13]),
static_cast<float>(modelview_matrix[14])));