人生第一次写博客,有错误的地方,给我回复下 , 话不多说,直接上代码
#include
#include
//#include
#include
#include
#include
#include
#include"ColorT.h"
#include
dlib::shape_predictor sp;
int detectctFace(cv::Mat &mat, std::vector
{
dlib::full_object_detection shape1;
cv::Mat mat1, gra;
mat.copyTo(mat1);
cv::cvtColor(mat1, gra, CV_BGR2GRAY);
int * pResults = NULL;
unsigned char * pBuffer = (unsigned char *)malloc(0x20000);
if (!pBuffer)
{
fprintf(stderr, "Can not alloc buffer.\n");
return -1;
}
pResults = facedetect_multiview_reinforce(pBuffer, (unsigned char*)(gra.ptr(0)), gra.cols, gra.rows, (int)gra.step, 1.15f, 5, 15, 0, 0);
std::vector
point.clear();
if (*pResults > 0)
{
for (int i = 0; i < (pResults ? *pResults : 0); i++)
{
dlib::rectangle det;
short * p = ((short*)(pResults + 1)) + 142 * i;
int x = p[0];
int y = p[1];
int w = p[2];
int h = p[3];
if (w > 0 && h > 0 && x + w < gra.cols&&y + h < gra.rows)
{
det.set_top(y);
det.set_left(x);
det.set_bottom(y + h);
det.set_right(x + w);
dlib::cv_image
shape1 = sp(cimg, det); //特征点检测
for (int s = 0; s < 17; s++)
{
cv::Point2f pt(shape1.part(s).x(), shape1.part(s).y());
point.push_back(pt);
}
for (int s = 26; s > 16; s--)
{
cv::Point2f pt(shape1.part(s).x(), shape1.part(s).y());
point.push_back(pt);
}
}
}
}
free(pBuffer);
pResults = NULL;
}
//这个函数是将三角剖分后的三角对点与人脸的特征点位置相匹配,拿出三角对的序列
void getImgTriangleList(Size size, Subdiv2D &subdiv, vector
{
Rect rect(0, 0, size.width, size.height);
vector
subdiv.getTriangleList(triangleList);
vector
cout << "triangleList Size is:" << triangleList.size() << endl;
for (size_t i = 0; i < triangleList.size(); i++)
{
Vec6i t = triangleList[i];
pt[0] = Point(t[0], t[1]);
pt[1] = Point(t[2], t[3]);
pt[2] = Point(t[4], t[5]);
if (rect.contains(pt[0]) && rect.contains(pt[1]) && rect.contains(pt[2]))
{
for (int j = 0; j < 3; j++)
for (int k = 0; k < point.size(); k++)
{
if (pt[j].x == point[k].x&& pt[j].y == point[k].y)
{
triangleSeq.push_back(k);
break;
}
}
}
}
}
//人脸融合函数
void morphFaceFunc(Mat srcA, Mat &srcB, vector
{
Mat srcBCopy;
srcB.copyTo(srcBCopy); //原图复制一个
int size = triangleSeq.size();
for (int j = 0; j < size; j += 3) //对所有的三角形遍历并进行复制
{
vector
vector
//A图人脸上的三个点
pointAFace[0] = pointA[triangleSeq[j]];
pointAFace[1] = pointA[triangleSeq[j + 1]];
pointAFace[2] = pointA[triangleSeq[j + 2]];
//B图对应A 图的三个点,映射关系
pointBFace[0] = pointB[triangleSeq[j]];
pointBFace[1] = pointB[triangleSeq[j + 1]];
pointBFace[2] = pointB[triangleSeq[j + 2]];
//为三个点包一个矩形
Rect rectA = boundingRect(pointAFace);
Rect rectB = boundingRect(pointBFace);
Point2f pointAf[3];
Point2f pointBf[3];
//计算相对于刚才rectA 的点,以及对应于rectB 的点 ,为之后的仿射变换做准备
pointAf[0] = Point(pointAFace[0].x - rectA.x, pointAFace[0].y - rectA.y);
pointAf[1] = Point(pointAFace[1].x - rectA.x, pointAFace[1].y - rectA.y);
pointAf[2] = Point(pointAFace[2].x - rectA.x, pointAFace[2].y - rectA.y);
pointBf[0] = Point(pointBFace[0].x - rectB.x, pointBFace[0].y - rectB.y);
pointBf[1] = Point(pointBFace[1].x - rectB.x, pointBFace[1].y - rectB.y);
pointBf[2] = Point(pointBFace[2].x - rectB.x, pointBFace[2].y - rectB.y);
//获取Rect部分的ROI
Mat roiMat(srcA, rectA);
Mat maskA(srcA.size(), CV_8UC1);
maskA.setTo(0);
Mat maskB(srcB.size(), CV_8UC1);
maskB.setTo(0);
//用三个点做一个三角形的mask
cv::fillConvexPoly(maskA, pointAFace, Scalar(255), 16);
cv::fillConvexPoly(maskB, pointBFace, Scalar(255), 16);
Mat skinA(rectA.size(), CV_8UC3);
skinA.setTo(0);
Mat MaskAROI, MaskBROI;
maskA(rectA).copyTo(MaskAROI);
maskB(rectB).copyTo(MaskBROI);
roiMat.copyTo(skinA, MaskAROI);
Mat outImg(rectB.size(), srcB.type());
Mat outMaskB(rectB.size(), CV_8UC1);//), outImg2;
//将 a 脸上的一个三角形纹理向b脸上进行仿射变换,同时把mask也进行仿射变换,如果直接用b图的三角形 mask
//进行复制,人脸上会有缝隙产生
cv::Mat warpMat = cv::getAffineTransform(pointAf, pointBf);
cv::warpAffine(skinA, outImg, warpMat, outImg.size(), cv::INTER_NEAREST, cv::BORDER_REFLECT_101);// cv::BORDER_REFLECT_101);
cv::warpAffine(MaskAROI, outMaskB, warpMat, outMaskB.size(), cv::INTER_NEAREST, cv::BORDER_CONSTANT,Scalar(0));
Mat roiNewMat(srcB, rectB);
outImg.copyTo(roiNewMat, outMaskB);
imshow("test", srcB);
waitKey(10);
}
//整个人脸的mask
Mat maskFace(srcB.size(), CV_8UC1);
cv::fillConvexPoly(maskFace, pointB, Scalar(255), 8, 0);
//mask 的大致中心点
int x1 = (pointB[0].x + pointB[16].x) / 2;
int y1 = ((pointB[19].y + pointB[24].y) / 2 + pointB[8].y) / 2;
//泊松融合
seamlessClone(srcB, srcBCopy, maskFace, cv::Point(x1, y1), srcB, 1);
imshow("test", srcB);
waitKey(0);
}
int main()
{
string shape_model = "shape_predictor_68_face_landmarks.dat";
cout << "加载模型文件" << endl;
dlib::deserialize(shape_model) >> sp;
Mat srcA = imread("A.jpg");
Mat srcB = imread("B.jpg");
Size sizeA = srcA.size();
Size sizeB= srcB.size();
Rect rectA(0, 0, sizeA.width, sizeA.height);
Rect rectB(0, 0, sizeB.width, sizeB.height);
//三角剖分的对象以及三角剖分的位置
Subdiv2D subdivA(rectA);
Subdiv2D subdivB(rectB);
//保存人脸特征点的
vector
cout << "开始人脸检测" << endl;
//人脸检测,以及特征点检测
detectctFace(srcA , pointA);
detectctFace(srcB, pointB);
//将检测到的人脸特征点插入到三角剖分里
for (int i = 0; i < pointA.size(); i++)
{
subdivA.insert(pointA[i]);
subdivB.insert(pointB[i]);
}
vector
vector
getImgTriangleList(sizeA, subdivA, pointA, triangleSeqA);
morphFaceFunc(srcA, srcB, pointA, pointB, triangleSeqA);
return 0;
}
原工程下载地址,哈哈,赚点积分而已
http://download.csdn.net/download/wz9ixk58/10269365