示例#1
0
	void Detection::doFacialComponentsExtractionSide(FaceGeometry& faceGeometry, const std::vector<ContourInfo>& componentContourInfo, const std::vector<ContourInfo>& faceContourInfo)
	{
		// we need at least 3 elements (left & right eye, mouth)
		if (componentContourInfo.size()<1 || faceContourInfo.size()<1)
		{
			throw std::exception("we need at least 1 region for classification as eye (side image)");
		}

		const ContourInfo& eye = componentContourInfo[0];
		const ContourInfo& face = faceContourInfo[0];
		
		faceGeometry.setDetectedPoint(FaceGeometry::SideEye, cv::Point2d(eye.cogX, eye.cogY));
		
						
		// find bounding polygon with at least 5 vertices
		std::vector<cv::Point> polygonPoints;
		double precission = 50.0;
		while (polygonPoints.size() < 5)
		{				
			cv::approxPolyDP(face.contour, polygonPoints, precission, true);
			precission = precission / 2;
		}
			
		

		// nose tip is rightmost point (of this polygon)		
		size_t noseIdx = 0;
		faceGeometry.setDetectedPoint(FaceGeometry::SideNoseTip, cv::Point2d(0, 0));
		for (size_t i = 0; i < polygonPoints.size(); ++i)
		{
			if (polygonPoints[i].x > faceGeometry.getDetectedPoint(FaceGeometry::SideNoseTip).x)
			{
				faceGeometry.setDetectedPoint(FaceGeometry::SideNoseTip, polygonPoints[i]);
				noseIdx = i;
			}
		}


		// find chin: which direction must be searched for in the polygon?
		bool incIdx = false;
		const size_t numPolygonPoints = polygonPoints.size();
		if (polygonPoints[(noseIdx + 1) % numPolygonPoints].y > faceGeometry.getDetectedPoint(FaceGeometry::SideNoseTip).y)
		{
			incIdx = true;
		}

		// search for the following pattern: find a convex and a neighboured concave polygon part under the nose
		faceGeometry.setDetectedPoint(FaceGeometry::SideChin, cv::Point2d(0, 0));
		for (size_t i = noseIdx, j = 0; j<numPolygonPoints; incIdx ? ++i : --i, ++j)
		{
			// don't check the nose itself
			if (j==0)
			{
				continue;
			}
				
			// get prev, curr and next point
			cv::Point prevprev = polygonPoints[(incIdx ? (i - 2) : (i + 2)) % numPolygonPoints];
			cv::Point prev = polygonPoints[(incIdx ? (i - 1) : (i + 1)) % numPolygonPoints];
			cv::Point curr = polygonPoints[i % numPolygonPoints];
			cv::Point next = polygonPoints[(incIdx ? (i + 1) : (i - 1)) % numPolygonPoints];

			if (isConcave(prev, curr, next) && !isConcave(prevprev, prev, curr))
			{
				faceGeometry.setDetectedPoint(FaceGeometry::SideChin, prev);
				break;
			}
		}					


		// find back side of head
		const cv::Point chinPoint = faceGeometry.getDetectedPoint(FaceGeometry::SideChin);
		cv::Point backPoint;
		for (int x = 0; x<m_FaceExtracted[sideImgNr].cols; ++x)
		{			
			if (m_FaceExtracted[sideImgNr].at<unsigned char>(cv::Point(x, chinPoint.y))!=0)
			{
				backPoint.x = x;
				backPoint.y = chinPoint.y;
				break;
			}
		}
		faceGeometry.setDetectedPoint(FaceGeometry::SideBack, backPoint);


		// create face mask
		cv::Mat mask(imgSize, imgSize, CV_8U);
		mask.setTo(0);
		cv::drawContours(mask, std::vector<std::vector<cv::Point> > {face.contour}, 0, 255, -1);
		m_FaceMask.push_back(mask);
		

		// show debug info
		cv::Mat tmp = getCopyOfOriginal(sideImgNr);
		cv::drawContours(tmp, std::vector<std::vector<cv::Point> > {eye.contour}, 0, cv::Scalar(255, 0, 0), -1);
		dbgShow(tmp, "doFacialComponentsExtractionSide");

		// and the polygon
		cv::Mat tmpChin = cv::Mat::zeros(imgSize, imgSize, CV_8UC3);
		cv::drawContours(tmpChin, std::vector<std::vector<cv::Point> > {face.contour}, 0, cv::Scalar(100, 100, 100), -1);
		cv::RNG rng(0);
		for (size_t i = 0; i < numPolygonPoints; ++i)
		{
			std::cout << "Point: " << polygonPoints[i] << "\n";
			cv::line(tmpChin, polygonPoints[i], polygonPoints[(i + 1) % numPolygonPoints], cv::Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 5);
		}

		dbgShow(tmpChin, "doFacialComponentsExtractionSide");
	}
示例#2
0
	void Detection::doFacialComponentsExtractionFront(FaceGeometry& faceGeometry, const std::vector<ContourInfo>& componentContourInfo, const std::vector<ContourInfo>& faceContourInfo)
	{
		// we need at least 3 elements (left & right eye, mouth)
		if (componentContourInfo.size()<3 || faceContourInfo.size()<1)
		{
			throw std::exception("we need at least 3 regions for classification as left & right eye, mouth (front image)");
		}
		
		std::vector<ContourInfo> biggestThree(componentContourInfo.begin(), componentContourInfo.begin() + 3);

		ContourInfo mouth;
		std::vector<ContourInfo> eyes;
		for (size_t i = 0; i < biggestThree.size(); ++i)
		{
			if (biggestThree[i].cogY > faceContourInfo[0].cogY)
			{
				mouth = biggestThree[i];
			}
			else
			{
				eyes.push_back(biggestThree[i]);
			}
		}

		// we need at least 3 elements (left & right eye, mouth)
		if (eyes.size()!=2)
		{
			throw std::exception("couldn't identify both eyes");
		}


		// left / right eye
		ContourInfo leftEye = eyes[0].cogX < eyes[1].cogX ? eyes[0] : eyes[1];
		ContourInfo rightEye = eyes[0].cogX > eyes[1].cogX ? eyes[0] : eyes[1];

		faceGeometry.setDetectedPoint(FaceGeometry::FrontLeftEye, cv::Point2d(leftEye.cogX, leftEye.cogY));
		faceGeometry.setDetectedPoint(FaceGeometry::FrontRightEye, cv::Point2d(rightEye.cogX, rightEye.cogY));
		faceGeometry.setDetectedPoint(FaceGeometry::FrontMouth, cv::Point2d(mouth.cogX, mouth.cogY));		



		// find sides of face (xmin, xmax)
		const cv::Point eyePos = faceGeometry.getDetectedPoint(FaceGeometry::FrontLeftEye);
		cv::Point leftCheek, rightCheek;

		// left
		for (int x = 0; x<m_FaceExtracted[sideImgNr].cols; ++x)
		{
			if (m_FaceExtracted[frontImgNr].at<unsigned char>(cv::Point(x, eyePos.y)) != 0)
			{
				leftCheek.x = x;
				leftCheek.y = eyePos.y;
				break;
			}
		}

		// right 
		for (int x = m_FaceExtracted[sideImgNr].cols-1; x>=0; --x)
		{
			if (m_FaceExtracted[frontImgNr].at<unsigned char>(cv::Point(x, eyePos.y)) != 0)
			{
				rightCheek.x = x;
				rightCheek.y = eyePos.y;
				break;
			}
		}

		faceGeometry.setDetectedPoint(FaceGeometry::FrontLeftCheek, leftCheek);
		faceGeometry.setDetectedPoint(FaceGeometry::FrontRightCheek, rightCheek);
		

		// create face mask
		cv::Mat mask(imgSize,imgSize,CV_8U);
		mask.setTo(0);
		cv::drawContours(mask, std::vector<std::vector<cv::Point> > {faceContourInfo[0].contour}, 0, 255, -1);
		m_FaceMask.push_back(mask);		

		
		// show debug info
		cv::Mat tmp=getCopyOfOriginal(frontImgNr);
		cv::drawContours(tmp, std::vector<std::vector<cv::Point> > {leftEye.contour}, 0, cv::Scalar(255, 0, 0), -1);
		cv::drawContours(tmp, std::vector<std::vector<cv::Point> > {rightEye.contour}, 0, cv::Scalar(0, 255, 0), -1);
		cv::drawContours(tmp, std::vector<std::vector<cv::Point> > {mouth.contour}, 0, cv::Scalar(0, 0, 255), -1);			
		dbgShow(tmp, "doFacialComponentsExtractionFront");
	}