faceMorph.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #include <opencv2/imgproc/imgproc.hpp>
  2. #include <opencv2/highgui/highgui.hpp>
  3. #include <iostream>
  4. #include <fstream>
  5. #include <iomanip>
  6. #include <stdlib.h>
  7. using namespace cv;
  8. using namespace std;
  9. // Read points stored in the text files
  10. vector<Point2f> readPoints(string pointsFileName)
  11. {
  12. vector<Point2f> points;
  13. ifstream ifs(pointsFileName);
  14. float x, y;
  15. while(ifs >> x >> y)
  16. {
  17. points.push_back(Point2f(x,y));
  18. }
  19. return points;
  20. }
  21. // Apply affine transform calculated using srcTri and dstTri to src
  22. void applyAffineTransform(Mat &warpImage, Mat &src, vector<Point2f> &srcTri, vector<Point2f> &dstTri)
  23. {
  24. // Given a pair of triangles, find the affine transform.
  25. Mat warpMat = getAffineTransform( srcTri, dstTri );
  26. // Apply the Affine Transform just found to the src image
  27. warpAffine( src, warpImage, warpMat, warpImage.size(), INTER_LINEAR, BORDER_REFLECT_101);
  28. }
  29. // Warps and alpha blends triangular regions from img1 and img2 to img
  30. void morphTriangle(Mat &img1, Mat &img2, Mat &img, vector<Point2f> &t1, vector<Point2f> &t2, vector<Point2f> &t, double alpha)
  31. {
  32. // Find bounding rectangle for each triangle
  33. Rect r = boundingRect(t);
  34. Rect r1 = boundingRect(t1);
  35. Rect r2 = boundingRect(t2);
  36. // Offset points by left top corner of the respective rectangles
  37. vector<Point2f> t1Rect, t2Rect, tRect;
  38. vector<Point> tRectInt;
  39. for(int i = 0; i < 3; i++)
  40. {
  41. tRect.push_back( Point2f( t[i].x - r.x, t[i].y - r.y) );
  42. tRectInt.push_back( Point(t[i].x - r.x, t[i].y - r.y) ); // for fillConvexPoly
  43. t1Rect.push_back( Point2f( t1[i].x - r1.x, t1[i].y - r1.y) );
  44. t2Rect.push_back( Point2f( t2[i].x - r2.x, t2[i].y - r2.y) );
  45. }
  46. // Get mask by filling triangle
  47. Mat mask = Mat::zeros(r.height, r.width, CV_32FC3);
  48. fillConvexPoly(mask, tRectInt, Scalar(1.0, 1.0, 1.0), 16, 0);
  49. // Apply warpImage to small rectangular patches
  50. Mat img1Rect, img2Rect;
  51. img1(r1).copyTo(img1Rect);
  52. img2(r2).copyTo(img2Rect);
  53. Mat warpImage1 = Mat::zeros(r.height, r.width, img1Rect.type());
  54. Mat warpImage2 = Mat::zeros(r.height, r.width, img2Rect.type());
  55. applyAffineTransform(warpImage1, img1Rect, t1Rect, tRect);
  56. applyAffineTransform(warpImage2, img2Rect, t2Rect, tRect);
  57. // Alpha blend rectangular patches
  58. Mat imgRect = (1.0 - alpha) * warpImage1 + alpha * warpImage2;
  59. // Copy triangular region of the rectangular patch to the output image
  60. multiply(imgRect,mask, imgRect);
  61. multiply(img(r), Scalar(1.0,1.0,1.0) - mask, img(r));
  62. img(r) = img(r) + imgRect;
  63. }
  64. int main( int argc, char** argv)
  65. {
  66. string filename1("hillary_clinton.jpg");
  67. string filename2("ted_cruz.jpg");
  68. //alpha controls the degree of morph
  69. double alpha = 0.5;
  70. //Read input images
  71. Mat img1 = imread(filename1);
  72. Mat img2 = imread(filename2);
  73. //convert Mat to float data type
  74. img1.convertTo(img1, CV_32F);
  75. img2.convertTo(img2, CV_32F);
  76. //empty average image
  77. Mat imgMorph = Mat::zeros(img1.size(), CV_32FC3);
  78. //Read points
  79. vector<Point2f> points1 = readPoints( filename1 + ".txt");
  80. vector<Point2f> points2 = readPoints( filename2 + ".txt");
  81. vector<Point2f> points;
  82. //compute weighted average point coordinates
  83. for(int i = 0; i < points1.size(); i++)
  84. {
  85. float x, y;
  86. x = (1 - alpha) * points1[i].x + alpha * points2[i].x;
  87. y = ( 1 - alpha ) * points1[i].y + alpha * points2[i].y;
  88. points.push_back(Point2f(x,y));
  89. }
  90. //Read triangle indices
  91. ifstream ifs("tri.txt");
  92. int x,y,z;
  93. while(ifs >> x >> y >> z)
  94. {
  95. // Triangles
  96. vector<Point2f> t1, t2, t;
  97. // Triangle corners for image 1.
  98. t1.push_back( points1[x] );
  99. t1.push_back( points1[y] );
  100. t1.push_back( points1[z] );
  101. // Triangle corners for image 2.
  102. t2.push_back( points2[x] );
  103. t2.push_back( points2[y] );
  104. t2.push_back( points2[z] );
  105. // Triangle corners for morphed image.
  106. t.push_back( points[x] );
  107. t.push_back( points[y] );
  108. t.push_back( points[z] );
  109. morphTriangle(img1, img2, imgMorph, t1, t2, t, alpha);
  110. }
  111. // Display Result
  112. imshow("Morphed Face", imgMorph / 255.0);
  113. waitKey(0);
  114. return 0;
  115. }