Advertisement
Guest User

Untitled

a guest
Nov 17th, 2017
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.59 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. #include <opencv2/dnn.hpp>
  3. #include <opencv2/imgproc.hpp>
  4. #include <opencv2/highgui.hpp>
  5.  
  6. using namespace cv;
  7. using namespace cv::dnn;
  8. using namespace std;
  9.  
  10. /* checks if a cropped ear image is left oriented */
  11. /* input is a 96x96 image */
  12. bool isLeft(Mat img) {
  13.     static bool first = true;
  14.     static Net net;
  15.  
  16.     if(first) {
  17.         first = false;
  18.         net = readNetFromTensorflow("model-side.pb");
  19.         if(net.empty()) {
  20.             cerr << "ERROR: Could not load the CNN for side classification" << endl;
  21.             exit(1);
  22.         }
  23.     }
  24.  
  25.     Mat inputBlob = blobFromImage(img);
  26.     inputBlob /= 255.0;
  27.     net.setInput(inputBlob, "Placeholder");
  28.     Mat result = net.forward("side_/out/MatMul");
  29.  
  30.     cout << result.at<float>(0,0) << " " << result.at<float>(0,1) << endl;
  31.  
  32.     return result.at<float>(0,0) > result.at<float>(0,1);
  33. }
  34.  
  35. /* detects landmarks in a left oriented cropped ear image */
  36. /* input is a 96x96 image */
  37. typedef enum __stage {FIRST, SECOND} stage;
  38. void detectLandmarks(Mat img, vector<Point2d> &ldmk, stage s) {
  39.     static bool first = true;
  40.     static Net net1, net2;
  41.  
  42.     if(first) {
  43.         first = false;
  44.         net1 = readNetFromTensorflow("model-stage1.pb");
  45.         net2 = readNetFromTensorflow("model-stage2.pb");
  46.         if(net1.empty() || net2.empty()) {
  47.             cerr << "ERROR: Could not load the CNNs for landmark detection" << endl;
  48.             exit(1);
  49.         }
  50.     }
  51.  
  52.     Mat result, inputBlob = blobFromImage(img);
  53.     inputBlob /= 255.0;
  54.     if(s == FIRST) {
  55.         net1.setInput(inputBlob);
  56.         result = net1.forward("ear_ang45_3_sca20_r_tra20_r_e/out/MatMul");
  57.     }
  58.     else {
  59.         net2.setInput(inputBlob);
  60.         result = net2.forward("ear_ang45_3_sca20_r_tra20_r_e/out/MatMul");
  61.     }
  62.     result *= 48;
  63.     result += 48;
  64.  
  65.     ldmk.clear();
  66.     for(int i=0; i < 55; i++) {
  67.         ldmk.push_back(Point2d(result.at<float>(0,i*2), result.at<float>(0,i*2+1)));
  68.         cout << ldmk[i].x << "," << ldmk[i].y << " ";
  69.     }
  70.     cout << endl;
  71. }
  72.  
  73. /* extracts descriptor from a left oriented normalized ear image */
  74. /* input is a 128x128 image */
  75. Mat extractDescriptor(Mat img) {
  76.     static bool first = true;
  77.     static Net net;
  78.  
  79.     if(first) {
  80.         first = false;
  81.         net = readNetFromTensorflow("model-descriptor.pb");
  82.         if(net.empty()) {
  83.             cerr << "ERROR: Could not load the CNN for side classification" << endl;
  84.             exit(1);
  85.         }
  86.     }
  87.  
  88.     Mat inputBlob = blobFromImage(img);
  89.     inputBlob /= 255.0;
  90.     net.setInput(inputBlob);
  91.     Mat result = net.forward("MatMul");
  92.  
  93.     for(int i=0; i < result.dims; i++)
  94.         cout << result.size[i] << " ";
  95.     cout << endl;
  96.  
  97.     return result.clone();
  98. }
  99.  
  100. /* interpolate ear image */
  101. void normalizeImage(Mat image, Mat &output, int size, double scale, double ang, double cx, double cy) {
  102.     output.create(size, size, CV_8UC1);
  103.     double ratio = (scale/((size-1)/2.0));
  104.     for(int i=0; i < size; i++)
  105.         for(int j=0; j < size; j++) {
  106.             double xt = ratio*(j-(size-1)/2.0), yt = ratio*(i-(size-1)/2.0);
  107.             double x = xt*cos(ang)-yt*sin(ang)+cx, y = xt*sin(ang)+yt*cos(ang)+cy;
  108.             int u = x, v = y;
  109.             double ul = x-u, vl = y-v;
  110.             int u1 = u+1, v1 = v+1;
  111.             u = max(0, min(image.cols-1, u));
  112.             u1 = max(0, min(image.cols-1, u1));
  113.             v = max(0, min(image.rows-1, v));
  114.             v1 = max(0, min(image.rows-1, v1));
  115.  
  116.             double tmp = image.at<uchar>(v,u)*(1.0-ul)*(1.0-vl) + image.at<uchar>(v,u1)*ul*(1.0-vl) + image.at<uchar>(v1,u)*(1.0-ul)*vl + image.at<uchar>(v1,u1)*ul*vl;
  117.             output.at<uchar>(i,j) = max(0.0,min(255.0,tmp));   
  118.         }
  119. }
  120.  
  121. /* adjust pose parameters using landmarks */
  122. void adjustParameters(vector<Point2d> ldmk, int size, double &scale, double &ang, double &cx, double &cy) {
  123.     double ratio = (scale/((size-1)/2.0));
  124.  
  125.     /* align landmark coordinate space to the original image */
  126.     /* compute principal components and bounding box for aligned landmarks */
  127.     Mat data_pts = Mat(55, 2, CV_64FC1);
  128.     Point2d tl = {DBL_MAX, DBL_MAX}, br = {0.0, 0.0};
  129.     for(int i=0; i < 55; i++) {
  130.         double xt = ratio*(ldmk[i].x-(size-1)/2.0), yt = ratio*(ldmk[i].y-(size-1)/2.0);
  131.         data_pts.at<double>(i, 0) = xt*cos(ang)-yt*sin(ang)+cx;
  132.         data_pts.at<double>(i, 1) = xt*sin(ang)+yt*cos(ang)+cy;
  133.         tl.x = min(tl.x, data_pts.at<double>(i, 0));
  134.         tl.y = min(tl.y, data_pts.at<double>(i, 1));
  135.         br.x = max(br.x, data_pts.at<double>(i, 0));
  136.         br.y = max(br.y, data_pts.at<double>(i, 1));
  137.     }
  138.     PCA pca_analysis(data_pts, Mat(), CV_PCA_DATA_AS_ROW);
  139.  
  140.     /* set orientation of the ear as the direction of the first principal component */
  141.     double angle = atan2(pca_analysis.eigenvectors.at<double>(0, 1), pca_analysis.eigenvectors.at<double>(0, 0));
  142.     while(angle < 0.0)
  143.         angle += 2.0*M_PI;
  144.     if(angle > M_PI)
  145.         angle -= M_PI;
  146.     ang = angle-M_PI/2.0;
  147.  
  148.     /* set scale as two times the deviation of the first principal component */
  149.     scale = 2.0*sqrt(pca_analysis.eigenvalues.at<double>(0, 0));
  150.  
  151.     /* set center as the center of the bounding box */
  152.     cx = (tl.x+br.x)/2.0;
  153.     cy = (tl.y+br.y)/2.0;
  154. }
  155.  
  156. /* magic function */
  157. int main(int argc, char **argv) {
  158.     const int PREPROC_SIZE = 96;                                    // image size for side classification and landmark detection
  159.     const int DESCRIPT_SIZE = 128;                                  // image size for cnn description
  160.  
  161.     /* load cropped ear image */
  162.     Mat image = imread(argv[1], IMREAD_GRAYSCALE), interpolated;
  163.  
  164.     double scale = (max(image.rows, image.cols)-1.0)/2.0;           // set largest image axis as initial scale
  165.     double ang = 0.0;                                               // orientation unknown
  166.     double cx = (image.cols-1.0)/2.0, cy = (image.rows-1.0)/2.0;    // use center of the image as initial ear center
  167.  
  168.     /* normalize image using initial guesses for ear location, size and orientation */
  169.     normalizeImage(image, interpolated, PREPROC_SIZE, scale, ang, cx, cy);
  170.  
  171.     while(waitKey(10) < 0)
  172.         imshow("img", interpolated);
  173.  
  174.     /* check if the ear is left-oriented and flip it if it is not */
  175.     if(!isLeft(interpolated)) {
  176.         Mat tmp;
  177.         flip(interpolated, tmp, 1);
  178.         tmp.copyTo(interpolated);
  179.         flip(image, tmp, 1);
  180.         tmp.copyTo(image);
  181.     }
  182.  
  183.     while(waitKey(10) < 0)
  184.         imshow("img", interpolated);
  185.  
  186.     vector<Point2d> landmarks;                                      // vector with 2d coordinates of ear landmarks
  187.  
  188.     /* detect landmarks using stage 1 (robust to intense variations) */
  189.     detectLandmarks(interpolated, landmarks, FIRST);
  190.  
  191.     for(int i=0; i < landmarks.size(); i++)
  192.         circle(interpolated, Point(landmarks[i].x, landmarks[i].y), 2, Scalar(255), -1);
  193.  
  194.     while(waitKey(10) < 0)
  195.         imshow("img", interpolated);
  196.  
  197.     /* normalize image using adjusted parameters */
  198.     adjustParameters(landmarks, PREPROC_SIZE, scale, ang, cx, cy);
  199.     normalizeImage(image, interpolated, DESCRIPT_SIZE, scale, ang, cx, cy);
  200.  
  201.     while(waitKey(10) < 0)
  202.         imshow("img", interpolated);
  203.  
  204.     /* extract discriminant descriptor */
  205.     Mat descriptor = extractDescriptor(interpolated);
  206. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement