#include "opencv2/core.hpp"#include "opencv2/imgproc.hpp"c..._ncnn 人脸对齐">
当前位置:   article > 正文

retinaface人脸对齐_ncnn 人脸对齐

ncnn 人脸对齐

在搭建人脸识别工程的时候,人脸对齐部分参考ncnn_example中的align模块,如果有用到的,可以在作者主页上加星。

这里把代码也贴出来:

  1. //aligner.cpp
  2. #include "aligner.h"
  3. #include <iostream>
  4. #include "opencv2/core.hpp"
  5. #include "opencv2/imgproc.hpp"
  6. class Aligner::Impl {
  7. public:
  8. int Align(const cv::Mat& img_src, const std::vector<cv::Point2f>& keypoints, cv::Mat* face_aligned);
  9. private:
  10. cv::Mat MeanAxis0(const cv::Mat &src);
  11. cv::Mat ElementwiseMinus(const cv::Mat &A, const cv::Mat &B);
  12. cv::Mat VarAxis0(const cv::Mat &src);
  13. int MatrixRank(cv::Mat M);
  14. cv::Mat SimilarTransform(const cv::Mat& src, const cv::Mat& dst);
  15. float points_dst[5][2] = {
  16. { 30.2946f + 8.0f, 51.6963f },
  17. { 65.5318f + 8.0f, 51.5014f },
  18. { 48.0252f + 8.0f, 71.7366f },
  19. { 33.5493f + 8.0f, 92.3655f },
  20. { 62.7299f + 8.0f, 92.2041f }
  21. };
  22. };
  23. Aligner::Aligner() {
  24. impl_ = new Impl();
  25. }
  26. Aligner::~Aligner() {
  27. if (impl_) {
  28. delete impl_;
  29. }
  30. }
  31. int Aligner::Align(const cv::Mat & img_src,
  32. const std::vector<cv::Point2f>& keypoints, cv::Mat * face_aligned) {
  33. return impl_->Align(img_src, keypoints, face_aligned);
  34. }
  35. int Aligner::Impl::Align(const cv::Mat & img_src,
  36. const std::vector<cv::Point2f>& keypoints, cv::Mat * face_aligned) {
  37. std::cout << "start align face." << std::endl;
  38. if (img_src.empty()) {
  39. std::cout << "input empty." << std::endl;
  40. return 10001;
  41. }
  42. if (keypoints.size() == 0) {
  43. std::cout << "keypoints empty." << std::endl;
  44. return 10001;
  45. }
  46. float points_src[5][2] = {
  47. {keypoints[104].x, keypoints[104].y},
  48. {keypoints[105].x, keypoints[105].y},
  49. {keypoints[46].x, keypoints[46].y },
  50. {keypoints[84].x, keypoints[84].y },
  51. {keypoints[90].x, keypoints[90].y}
  52. };
  53. cv::Mat src_mat(5, 2, CV_32FC1, points_src);
  54. cv::Mat dst_mat(5, 2, CV_32FC1, points_dst);
  55. cv::Mat transform = SimilarTransform(src_mat, dst_mat);
  56. face_aligned->create(112, 112, CV_32FC3);
  57. cv::Mat transfer_mat = transform(cv::Rect(0, 0, 3, 2));
  58. cv::warpAffine(img_src.clone(), *face_aligned, transfer_mat, cv::Size(112, 112), 1, 0, 0);
  59. std::cout << "end align face." << std::endl;
  60. return 0;
  61. }
  62. cv::Mat Aligner::Impl::MeanAxis0(const cv::Mat & src) {
  63. int num = src.rows;
  64. int dim = src.cols;
  65. // x1 y1
  66. // x2 y2
  67. cv::Mat output(1, dim, CV_32FC1);
  68. for (int i = 0; i < dim; i++) {
  69. float sum = 0;
  70. for (int j = 0; j < num; j++) {
  71. sum += src.at<float>(j, i);
  72. }
  73. output.at<float>(0, i) = sum / num;
  74. }
  75. return output;
  76. }
  77. cv::Mat Aligner::Impl::ElementwiseMinus(const cv::Mat & A, const cv::Mat & B) {
  78. cv::Mat output(A.rows, A.cols, A.type());
  79. assert(B.cols == A.cols);
  80. if (B.cols == A.cols) {
  81. for (int i = 0; i < A.rows; i++) {
  82. for (int j = 0; j < B.cols; j++) {
  83. output.at<float>(i, j) = A.at<float>(i, j) - B.at<float>(0, j);
  84. }
  85. }
  86. }
  87. return output;
  88. }
  89. cv::Mat Aligner::Impl::VarAxis0(const cv::Mat & src) {
  90. cv::Mat temp_ = ElementwiseMinus(src, MeanAxis0(src));
  91. cv::multiply(temp_, temp_, temp_);
  92. return MeanAxis0(temp_);
  93. }
  94. int Aligner::Impl::MatrixRank(cv::Mat M) {
  95. cv::Mat w, u, vt;
  96. cv::SVD::compute(M, w, u, vt);
  97. cv::Mat1b nonZeroSingularValues = w > 0.0001;
  98. int rank = countNonZero(nonZeroSingularValues);
  99. return rank;
  100. }
  101. /*
  102. References: "Least-squares estimation of transformation parameters between two point patterns", Shinji Umeyama, PAMI 1991, DOI: 10.1109/34.88573
  103. Anthor: Jack Yu
  104. */
  105. cv::Mat Aligner::Impl::SimilarTransform(const cv::Mat & src, const cv::Mat & dst) {
  106. int num = src.rows;
  107. int dim = src.cols;
  108. cv::Mat src_mean = MeanAxis0(src);
  109. cv::Mat dst_mean = MeanAxis0(dst);
  110. cv::Mat src_demean = ElementwiseMinus(src, src_mean);
  111. cv::Mat dst_demean = ElementwiseMinus(dst, dst_mean);
  112. cv::Mat A = (dst_demean.t() * src_demean) / static_cast<float>(num);
  113. cv::Mat d(dim, 1, CV_32F);
  114. d.setTo(1.0f);
  115. if (cv::determinant(A) < 0) {
  116. d.at<float>(dim - 1, 0) = -1;
  117. }
  118. cv::Mat T = cv::Mat::eye(dim + 1, dim + 1, CV_32F);
  119. cv::Mat U, S, V;
  120. cv::SVD::compute(A, S, U, V);
  121. // the SVD function in opencv differ from scipy .
  122. int rank = MatrixRank(A);
  123. if (rank == 0) {
  124. assert(rank == 0);
  125. }
  126. else if (rank == dim - 1) {
  127. if (cv::determinant(U) * cv::determinant(V) > 0) {
  128. T.rowRange(0, dim).colRange(0, dim) = U * V;
  129. }
  130. else {
  131. int s = d.at<float>(dim - 1, 0) = -1;
  132. d.at<float>(dim - 1, 0) = -1;
  133. T.rowRange(0, dim).colRange(0, dim) = U * V;
  134. cv::Mat diag_ = cv::Mat::diag(d);
  135. cv::Mat twp = diag_ * V; //np.dot(np.diag(d), V.T)
  136. cv::Mat B = cv::Mat::zeros(3, 3, CV_8UC1);
  137. cv::Mat C = B.diag(0);
  138. T.rowRange(0, dim).colRange(0, dim) = U * twp;
  139. d.at<float>(dim - 1, 0) = s;
  140. }
  141. }
  142. else {
  143. cv::Mat diag_ = cv::Mat::diag(d);
  144. cv::Mat twp = diag_ * V.t(); //np.dot(np.diag(d), V.T)
  145. cv::Mat res = U * twp; // U
  146. T.rowRange(0, dim).colRange(0, dim) = -U.t()* twp;
  147. }
  148. cv::Mat var_ = VarAxis0(src_demean);
  149. float val = cv::sum(var_).val[0];
  150. cv::Mat res;
  151. cv::multiply(d, S, res);
  152. float scale = 1.0 / val * cv::sum(res).val[0];
  153. T.rowRange(0, dim).colRange(0, dim) = -T.rowRange(0, dim).colRange(0, dim).t();
  154. cv::Mat temp1 = T.rowRange(0, dim).colRange(0, dim); // T[:dim, :dim]
  155. cv::Mat temp2 = src_mean.t();
  156. cv::Mat temp3 = temp1 * temp2;
  157. cv::Mat temp4 = scale * temp3;
  158. T.rowRange(0, dim).colRange(dim, dim + 1) = -(temp4 - dst_mean.t());
  159. T.rowRange(0, dim).colRange(0, dim) *= scale;
  160. return T;
  161. }

 

  1. // aligner.h
  2. #ifndef _FACE_ALIGNER_H_
  3. #define _FACE_ALIGNER_H_
  4. #include "opencv2/core.hpp"
  5. class Aligner {
  6. public:
  7. Aligner();
  8. ~Aligner();
  9. int Align(const cv::Mat & img_src,
  10. const std::vector<cv::Point2f>& keypoints, cv::Mat * face_aligned);
  11. private:
  12. class Impl;
  13. Impl* impl_;
  14. };
  15. #endif // !_FACE_ALIGNER_H_

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/284963
推荐阅读
相关标签
  

闽ICP备14008679号