Switch to unified view

a b/src/manual_registration.cpp
1
#include <Rcpp.h>
2
3
// OpenCV
4
#include <opencv2/opencv.hpp>
5
#include "opencv2/xfeatures2d.hpp"
6
#include "opencv2/features2d.hpp"
7
#include "opencv2/shape/shape_transformer.hpp"
8
// #include <opencv2/imgproc.hpp>
9
10
// Auxiliary
11
#include "auxiliary.h"
12
13
// Namespaces
14
using namespace Rcpp;
15
using namespace std;
16
using namespace cv;
17
using namespace cv::xfeatures2d;
18
19
// align images with TPS algorithm
20
void alignImagesTPS(Mat &im1, Mat &im2, Mat &im1Reg, Rcpp::List &keypoints, 
21
                    Rcpp::NumericMatrix query_landmark, Rcpp::NumericMatrix reference_landmark)
22
{
23
24
  // seed
25
  cv::setRNGSeed(0);
26
  RNG rng(12345);
27
  Scalar value;
28
29
  // Get landmarks as Point2f
30
  std::vector<cv::Point2f> query_mat = numericMatrixToPoint2f(query_landmark);
31
  std::vector<cv::Point2f> ref_mat = numericMatrixToPoint2f(reference_landmark);
32
33
  // get matches
34
  std::vector<cv::DMatch> matches;
35
  for (unsigned int i = 0; i < ref_mat.size(); i++)
36
    matches.push_back(cv::DMatch(i, i, 0));
37
38
  // calculate transformation
39
  Ptr<ThinPlateSplineShapeTransformer> tps = cv::createThinPlateSplineShapeTransformer(0);
40
  tps->estimateTransformation(ref_mat, query_mat, matches);
41
42
  // save keypoints 
43
  keypoints[0] = point2fToNumericMatrix(ref_mat);
44
  keypoints[1] = point2fToNumericMatrix(query_mat); 
45
  
46
  // determine extension limits for both images
47
  int y_max = max(im1.rows, im2.rows);
48
  int x_max = max(im1.cols, im2.cols);
49
50
  // extend images
51
  cv::copyMakeBorder(im1, im1, 0.0, (int) (y_max - im1.rows), 0.0, (x_max - im1.cols), cv::BORDER_CONSTANT, Scalar(0, 0, 0));
52
53
  // transform image
54
  tps->warpImage(im1, im1Reg);
55
56
  // resize image
57
  cv::Mat im1Reg_cropped  = im1Reg(cv::Range(0,im2.size().height), cv::Range(0,im2.size().width));
58
  im1Reg = im1Reg_cropped.clone();
59
}
60
61
// align images with affine transformation with TPS algorithm
62
void alignImagesAffineTPS(Mat &im1, Mat &im2, Mat &im1Reg, Mat &h, Rcpp::List &keypoints,
63
                          Rcpp::NumericMatrix query_landmark, Rcpp::NumericMatrix reference_landmark)
64
{
65
  
66
  // seed
67
  cv::setRNGSeed(0);
68
  RNG rng(12345);
69
  Scalar value;
70
  
71
  // Get landmarks as Point2f
72
  std::vector<cv::Point2f> query_mat = numericMatrixToPoint2f(query_landmark);
73
  std::vector<cv::Point2f> ref_mat = numericMatrixToPoint2f(reference_landmark);
74
  
75
  // get matches
76
  std::vector<cv::DMatch> matches;
77
  for (unsigned int i = 0; i < ref_mat.size(); i++)
78
    matches.push_back(cv::DMatch(i, i, 0));
79
  
80
  // calculate homography transformation
81
  Mat im1Affine;
82
  // h = estimateAffine2D(query_mat, ref_mat);
83
  h = findHomography(query_mat, ref_mat);
84
  cv::warpPerspective(im1, im1Affine, h, im2.size());
85
  // cv::warpAffine(im1, im1Affine, h, im2.size());
86
  std::vector<cv::Point2f> query_reg;
87
  cv::perspectiveTransform(query_mat, query_reg, h);
88
  
89
  // calculate TPS transformation
90
  Ptr<ThinPlateSplineShapeTransformer> tps = cv::createThinPlateSplineShapeTransformer(0);
91
  tps->estimateTransformation(ref_mat, query_reg, matches);
92
  
93
  // save keypoints 
94
  keypoints[0] = point2fToNumericMatrix(ref_mat);
95
  keypoints[1] = point2fToNumericMatrix(query_reg); 
96
  
97
  // determine extension limits for both images
98
  int y_max = max(im1Affine.rows, im2.rows);
99
  int x_max = max(im1Affine.cols, im2.cols);
100
101
  // extend images
102
  cv::copyMakeBorder(im1Affine, im1Affine, 0.0, (int) (y_max - im1Affine.rows), 0.0, (x_max - im1Affine.cols), cv::BORDER_CONSTANT, Scalar(0, 0, 0));
103
104
  // transform image
105
  tps->warpImage(im1Affine, im1Reg);
106
  
107
  // resize image
108
  cv::Mat im1Reg_cropped  = im1Reg(cv::Range(0,im2.size().height), cv::Range(0,im2.size().width));
109
  im1Reg = im1Reg_cropped.clone();
110
}
111
112
// [[Rcpp::export]]
113
Rcpp::List manual_registeration_rawvector(Rcpp::RawVector ref_image, Rcpp::RawVector query_image,
114
                                          Rcpp::NumericMatrix reference_landmark, Rcpp::NumericMatrix query_landmark,
115
                                          const int width1, const int height1,
116
                                          const int width2, const int height2,
117
                                          Rcpp::String method)
118
{
119
  // Return data
120
  Rcpp::List out(2);
121
  Rcpp::List out_trans(2);
122
  Rcpp::List keypoints(2);
123
  Mat imReg, h;
124
  
125
  // Read reference image
126
  cv::Mat imReference = imageToMat(ref_image, width1, height1);
127
128
  // Read image to be aligned
129
  cv::Mat im = imageToMat(query_image, width2, height2);
130
131
132
  // Homography + Non-rigid (TPS)
133
  if(strcmp(method.get_cstring(), "Homography + Non-Rigid") == 0){
134
    alignImagesAffineTPS(im, imReference, imReg, 
135
                         h, keypoints,
136
                         query_landmark, reference_landmark);
137
  }
138
  
139
  // Non-rigid (TPS) only
140
  if(strcmp(method.get_cstring(), "Non-Rigid") == 0){
141
    alignImagesTPS(im, imReference, imReg, 
142
                   keypoints, 
143
                   query_landmark, reference_landmark);
144
  }
145
146
  // transformation matrix, can be either a matrix, set of keypoints or both
147
  out_trans[0] = matToNumericMatrix(h.clone());
148
  out_trans[1] = keypoints;
149
  out[0] = out_trans;
150
  
151
  // registered image
152
  out[1] = matToImage(imReg.clone());
153
154
  return out;
155
}