Diff of /src/image.cpp [000000] .. [413088]

Switch to unified view

a b/src/image.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
9
// Internal functions
10
#include "auxiliary.h"
11
12
using namespace Rcpp;
13
using namespace std;
14
using namespace cv;
15
using namespace cv::xfeatures2d;
16
17
////
18
// processing
19
////
20
21
// process images before keypoint detection
22
cv::Mat preprocessImage(Mat &im, const bool invert, const char* flipflop, const char* rotate)
23
{
24
  // normalize
25
  Mat imNorm;
26
  cv::normalize(im, imNorm, 0, 255, cv::NORM_MINMAX, CV_8UC1);
27
  
28
  // rotate image
29
  Mat imRotate;
30
  if(atoi(rotate) > 0){
31
    cv::rotate(imNorm, imRotate, (atoi(rotate)/90)-1);
32
  } else {
33
    imRotate = imNorm;
34
  }
35
  
36
  // Flipflop image
37
  Mat imFlipFlop;
38
  if(strcmp(flipflop, "Flip") == 0){
39
    cv::flip(imRotate, imFlipFlop, 0);
40
  } else if(strcmp(flipflop, "Flop") == 0){
41
    cv::flip(imRotate, imFlipFlop, 1);
42
  } else if(strcmp(flipflop, "None") == 0){
43
    imFlipFlop = imRotate;
44
  }
45
  
46
  // invert/negate image and full processed image
47
  Mat imProcess;
48
  if(invert) {
49
    cv::bitwise_not(imFlipFlop, imProcess);
50
  } else {
51
    imProcess = imFlipFlop;
52
  }
53
  
54
  // return
55
  return imProcess;
56
}
57
58
// revert the processing on registrated images using the reference image
59
cv::Mat reversepreprocessImage(Mat &im, const char* flipflop, const char* rotate)
60
{
61
  
62
  // Flipflop image
63
  Mat imFlipFlop;
64
  if(strcmp(flipflop, "Flip") == 0){
65
    cv::flip(im, imFlipFlop, 0);
66
  } else if(strcmp(flipflop, "Flop") == 0){
67
    cv::flip(im, imFlipFlop, 1);
68
  } else if(strcmp(flipflop, "None") == 0){
69
    imFlipFlop = im;
70
  }
71
  
72
  // rotate image
73
  Mat imRotate;
74
  if(atoi(rotate) > 0){
75
    cv::rotate(imFlipFlop, imRotate, ((360-atoi(rotate))/90)-1);
76
  } else {
77
    imRotate = imFlipFlop;
78
  }
79
  
80
  // return
81
  return imRotate;
82
}
83
84
// [[Rcpp::export]]
85
Rcpp::RawVector warpImage(Rcpp::RawVector ref_image, Rcpp::RawVector query_image, 
86
                          Rcpp::List mapping,
87
                          const int width1, const int height1,
88
                          const int width2, const int height2)
89
{
90
  // Read reference image
91
  cv::Mat imReference = imageToMat(ref_image, width1, height1);
92
  
93
  // Read image to be aligned
94
  cv::Mat im = imageToMat(query_image, width2, height2);
95
  cv::Mat im_temp;
96
  
97
  // list 
98
  int n = mapping.size();
99
  
100
  // iterate over the list 
101
  for(int i=0; i<n; i++) {
102
    
103
    // get the current mapping
104
    Rcpp::List cur_mapping = mapping[i];
105
    
106
    // Get transformation matrix
107
    cv::Mat h = numericMatrixToMat(cur_mapping[0]);
108
    if(h.cols > 0){
109
      
110
      // transform coordinates
111
      cv::warpPerspective(im, im_temp, h, imReference.size()); 
112
      im = im_temp;
113
      
114
    } 
115
    
116
    // non-rigid warping
117
    if(cur_mapping[1] != R_NilValue){
118
      
119
      // get landmarks
120
      Rcpp::List keypoints = cur_mapping[1];
121
      std::vector<cv::Point2f> ref_mat = numericMatrixToPoint2f(keypoints[0]);
122
      std::vector<cv::Point2f> query_mat = numericMatrixToPoint2f(keypoints[1]);
123
      
124
      // get matches
125
      std::vector<cv::DMatch> matches;
126
      for (unsigned int i = 0; i < ref_mat.size(); i++)
127
        matches.push_back(cv::DMatch(i, i, 0));
128
      
129
      // calculate transformation
130
      Ptr<ThinPlateSplineShapeTransformer> tps = cv::createThinPlateSplineShapeTransformer(0);
131
      tps->estimateTransformation(ref_mat, query_mat, matches);
132
      
133
      // determine extension limits for both images
134
      int y_max = max(im.rows, imReference.rows);
135
      int x_max = max(im.cols, imReference.cols);
136
      
137
      // extend images
138
      cv::copyMakeBorder(im, im, 0.0, (int) (y_max - im.rows), 0.0, (x_max - im.cols), cv::BORDER_CONSTANT, Scalar(0, 0, 0));
139
      
140
      // transform image
141
      tps->warpImage(im, im_temp);
142
      
143
      // resize image
144
      cv::Mat im_temp_cropped  = im_temp(cv::Range(0,imReference.size().height), cv::Range(0,imReference.size().width));
145
      im_temp = im_temp_cropped.clone();
146
      
147
    } else {
148
      
149
      // pass registered object
150
      im_temp = im;
151
    }
152
    
153
    im = im_temp;
154
  }
155
  
156
  // return
157
  return matToImage(im);
158
} 
159
160
161
// [[Rcpp::export]]
162
Rcpp::RawVector warpImageAuto(Rcpp::RawVector ref_image, Rcpp::RawVector query_image, 
163
                              Rcpp::List mapping,
164
                              const int width1, const int height1,
165
                              const int width2, const int height2)
166
{
167
  // Get transformation matrix
168
  cv::Mat h = numericMatrixToMat(mapping[0]);
169
  
170
  // Read reference image
171
  cv::Mat imReference = imageToMat(ref_image, width1, height1);
172
  
173
  // Read image to be aligned
174
  cv::Mat im = imageToMat(query_image, width2, height2);
175
  
176
  // transform coordinates
177
  Mat imWarp;
178
  cv::warpPerspective(im, imWarp, h, imReference.size()); 
179
  
180
  // non-rigid warping
181
  cv::Mat imReg;
182
  if(mapping[1] != R_NilValue){
183
    
184
    // get landmarks
185
    Rcpp::List keypoints = mapping[1];
186
    std::vector<cv::Point2f> ref_mat = numericMatrixToPoint2f(keypoints[0]);
187
    std::vector<cv::Point2f> query_mat = numericMatrixToPoint2f(keypoints[1]);
188
    
189
    // get matches
190
    std::vector<cv::DMatch> matches;
191
    for (unsigned int i = 0; i < ref_mat.size(); i++)
192
      matches.push_back(cv::DMatch(i, i, 0));
193
    
194
    // calculate transformation
195
    Ptr<ThinPlateSplineShapeTransformer> tps = cv::createThinPlateSplineShapeTransformer(0);
196
    tps->estimateTransformation(ref_mat, query_mat, matches);
197
    
198
    // determine extension limits for both images
199
    int y_max = max(imWarp.rows, imReference.rows);
200
    int x_max = max(imWarp.cols, imReference.cols);
201
    
202
    // extend images
203
    cv::copyMakeBorder(imWarp, imWarp, 0.0, (int) (y_max - imWarp.rows), 0.0, (x_max - imWarp.cols), cv::BORDER_CONSTANT, Scalar(0, 0, 0));
204
    
205
    // transform image
206
    tps->warpImage(imWarp, imReg);
207
    
208
    // resize image
209
    // cv::resize(im1Reg, im1Reg, im2.size());
210
    cv::Mat imReg_cropped  = imReg(cv::Range(0,imReference.size().height), cv::Range(0,imReference.size().width));
211
    imReg = imReg_cropped.clone();
212
    
213
  } else {
214
    
215
    // pass registered object
216
    imReg = imWarp;
217
  }
218
  
219
  // return
220
  return matToImage(imReg);
221
}
222
223
224
// [[Rcpp::export]]
225
Rcpp::RawVector warpImageManual(Rcpp::RawVector ref_image, Rcpp::RawVector query_image, 
226
                                Rcpp::List mapping,
227
                                const int width1, const int height1,
228
                                const int width2, const int height2)
229
{
230
  // Get landmarks as Point2f and transformation matrix
231
  cv::Mat h = numericMatrixToMat(mapping[0]);
232
  Rcpp::List keypoints = mapping[1];
233
  std::vector<cv::Point2f> ref_mat = numericMatrixToPoint2f(keypoints[0]);
234
  std::vector<cv::Point2f> query_mat = numericMatrixToPoint2f(keypoints[1]);
235
  
236
  // Read reference image
237
  cv::Mat imReference = imageToMat(ref_image, width1, height1);
238
  
239
  // Read image to be aligned
240
  cv::Mat im = imageToMat(query_image, width2, height2);
241
  
242
  // transform coordinates
243
  Mat imWarp;
244
  if(h.cols > 0){
245
    cv::warpPerspective(im, imWarp, h, imReference.size()); 
246
  } else {
247
    imWarp = im;
248
  }
249
  
250
  // get matches
251
  std::vector<cv::DMatch> matches;
252
  for (unsigned int i = 0; i < ref_mat.size(); i++)
253
    matches.push_back(cv::DMatch(i, i, 0));
254
  
255
  // calculate transformation
256
  Ptr<ThinPlateSplineShapeTransformer> tps = cv::createThinPlateSplineShapeTransformer(0);
257
  tps->estimateTransformation(ref_mat, query_mat, matches);
258
  
259
  // determine extension limits for both images
260
  int y_max = max(imWarp.rows, imReference.rows);
261
  int x_max = max(imWarp.cols, imReference.cols);
262
  
263
  // extend images
264
  cv::copyMakeBorder(imWarp, imWarp, 0.0, (int) (y_max - imWarp.rows), 0.0, (x_max - imWarp.cols), cv::BORDER_CONSTANT, Scalar(0, 0, 0));
265
  
266
  // transform image
267
  cv::Mat imReg;
268
  tps->warpImage(imWarp, imReg);
269
  
270
  // resize image
271
  // cv::resize(im1Reg, im1Reg, im2.size());
272
  cv::Mat imReg_cropped  = imReg(cv::Range(0,imReference.size().height), cv::Range(0,imReference.size().width));
273
  imReg = imReg_cropped.clone();
274
  
275
  // return
276
  return matToImage(imReg);;
277
}