appkit  1.5.1
RoadNarrows Robotics Application Kit
WinCvIoI.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: RoadNarrows Robotics Application Tool Kit
4 //
5 // Library: librnr_win
6 //
7 // File: WinCvIoI.cxx
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2013-05-03 07:45:13 -0600 (Fri, 03 May 2013) $
12  * $Rev: 2904 $
13  *
14  * \brief RoadNarrows Robotics OpenCV Image of Interest class implementation.
15  *
16  * \author Robin Knight (robin.knight@roadnarrows.com)
17  * \author Daniel Packard (daniel@roadnarrows.com)
18  *
19  * \par Copyright
20  * \h_copy 2011-2017. RoadNarrows LLC.\n
21  * http://www.roadnarrows.com\n
22  * All Rights Reserved
23  */
24 /*
25  * @EulaBegin@
26  *
27  * Permission is hereby granted, without written agreement and without
28  * license or royalty fees, to use, copy, modify, and distribute this
29  * software and its documentation for any purpose, provided that
30  * (1) The above copyright notice and the following two paragraphs
31  * appear in all copies of the source code and (2) redistributions
32  * including binaries reproduces these notices in the supporting
33  * documentation. Substantial modifications to this software may be
34  * copyrighted by their authors and need not follow the licensing terms
35  * described here, provided that the new terms are clearly indicated in
36  * all files where they apply.
37  *
38  * IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
39  * OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
40  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
41  * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
42  * EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
43  * THE POSSIBILITY OF SUCH DAMAGE.
44  *
45  * THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
46  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
47  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
48  * "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
49  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
50  *
51  * @EulaEnd@
52  */
53 ////////////////////////////////////////////////////////////////////////////////
54 
55 #include <sys/types.h>
56 #include <stdarg.h>
57 #include <libgen.h>
58 
59 #include <cstring>
60 #include <iostream>
61 #include <fstream>
62 #include <cmath>
63 
64 #include "rnr/rnrconfig.h"
65 
66 #include "opencv2/core/core.hpp"
67 #include "opencv2/highgui/highgui.hpp"
68 
69 #include "rnr/appkit/Win.h"
70 #include "rnr/appkit/WinOpenCv.h"
71 #include "rnr/appkit/WinCvIoI.h"
72 
73 using namespace std;
74 using namespace cv;
75 using namespace rnr;
76 
77 
78 //.............................................................................
79 // Class WinCvIoI
80 //.............................................................................
81 
82 WinCvIoI::WinCvIoI(Size &sizeIoI,
83  Size &sizeTgt,
84  RotOp eOpRot,
85  AlignOp eOpAlign,
86  bool bCropToFit)
87 {
88  Rect rectRoIIoI(0, 0, sizeIoI.width, sizeIoI.height);
89 
90  setTransformParams(sizeIoI, rectRoIIoI, sizeTgt,
91  eOpRot, eOpAlign, bCropToFit);
92 }
93 
94 void WinCvIoI::setTransformParams(Size &sizeIoI,
95  Rect &rectRoIIoI,
96  Size &sizeTgt,
97  RotOp eOpRot,
98  AlignOp eOpAlign,
99  bool bCropToFit)
100 {
101  Point2f center; // rotation axis
102  Size sizeScaled; // size of rotated and resized image
103  int x, y; // working coordinates
104  int width, height; // working dimensions
105 
106  m_sizeIoI = sizeIoI;
107  m_rectRoIIoI = rectRoIIoI;
108  m_sizeTgt = sizeTgt;
109  m_eOpRot = eOpRot;
110  m_bOpRotate = false;
111  m_eOpAlign = eOpAlign;
112  m_bOpScale = false;
113  m_bOpCrop = false;
114 
115  // rotate about upper left corner (makes translation calculations easier)
116  center.x = 0;
117  center.y = 0;
118 
119  //
120  // Rotation and resized images
121  //
122  switch( eOpRot )
123  {
124  // 270 degree rotation = -90 degrees
125  case RotOp270:
126  // set 2x3 rotation matrix
127  m_matRot = getRotationMatrix2D(center, -90.0, 1.0);
128 
129  // translate
130  cvSetReal2D(&m_matRot, 0, 2, sizeIoI.height);
131  cvSetReal2D(&m_matRot, 1, 2, 0);
132 
133  // rotated IoI
134  m_sizeRotated = Size(rectRoIIoI.height, rectRoIIoI.width);
135  m_bOpRotate = true;
136 
137  break;
138 
139  // 180 degree rotation
140  case RotOp180:
141  // set 2x3 rotation matrix
142  m_matRot = getRotationMatrix2D(center, 180.0, 1.0);
143 
144  // translate
145  cvSetReal2D(&m_matRot, 0, 2, sizeIoI.width);
146  cvSetReal2D(&m_matRot, 1, 2, sizeIoI.height);
147 
148  // rotated IoI
149  m_sizeRotated = cvSize(rectRoIIoI.width, rectRoIIoI.height);
150  m_bOpRotate = true;
151 
152  break;
153 
154  // 90 degree rotation
155  case RotOp90:
156  // set 2x3 rotation matrix
157  m_matRot = getRotationMatrix2D(center, 90.0, 1.0);
158 
159  // translate
160  cvSetReal2D(&m_matRot, 0, 2, 0);
161  cvSetReal2D(&m_matRot, 1, 2, sizeIoI.width);
162 
163  // rotated IoI
164  m_sizeRotated = cvSize(rectRoIIoI.height, rectRoIIoI.width);
165  m_bOpRotate = true;
166 
167  break;
168 
169  // 0 degree rotation = no rotations
170  case RotOp0:
171  default:
172  // set 2x3 rotation matrix
173  m_matRot = getRotationMatrix2D(center, 0.0, 1.0);
174 
175  // rotated IoI
176  m_sizeRotated = cvSize(rectRoIIoI.width, rectRoIIoI.height);
177  m_bOpRotate = false;
178 
179  break;
180  }
181 
182  //
183  // Crop image to fit
184  //
185  if( bCropToFit )
186  {
187  // initialize
188  x = 0;
189  y = 0;
190  width = m_sizeRotated.width;
191  height = m_sizeRotated.height;
192  m_bOpCrop = false;
193 
194  if( m_sizeRotated.width > sizeTgt.width )
195  {
196  x = (m_sizeRotated.width - sizeTgt.width) / 2;
197  width = sizeTgt.width;
198  m_bOpCrop = true;
199  }
200  if( m_sizeRotated.height > sizeTgt.height )
201  {
202  y = (m_sizeRotated.height - sizeTgt.height) / 2;
203  height = sizeTgt.height;
204  m_bOpCrop = true;
205  }
206 
207  if( m_bOpCrop )
208  {
209  m_rectRoICropped = Rect(x, y, width, height);
210  }
211  }
212 
213  //
214  // Scale image to fit
215  //
216  else
217  {
218  // initialize
219  m_bOpScale = false;
220 
221  // best fit in a 4:3 aspect ratio
222  // RDK TODO allow for other aspect ratios
223  sizeScaled = calcMaxFit43(m_sizeRotated, sizeTgt);
224 
225  if( (sizeScaled.width < m_sizeRotated.width) ||
226  (sizeScaled.height < m_sizeRotated.height) )
227  {
228  m_sizeScaled = sizeScaled;
229  m_bOpScale = true;
230  }
231 
232  width = sizeScaled.width;
233  height = sizeScaled.height;
234  }
235 
236  //
237  // Alignment ROI
238  //
239  switch( eOpAlign )
240  {
241  // align center
242  case AlignOpCenter:
243  x = (sizeTgt.width - width) / 2;
244  y = (sizeTgt.height - height) / 2;
245  m_rectRoITgt = cvRect(x, y, width, height);
246  break;
247 
248  // align right
249  case AlignOpRight:
250  x = (sizeTgt.width - width) / 2;
251  y = sizeTgt.height - 1;
252  m_rectRoITgt = cvRect(x, y, width, height);
253  break;
254 
255  // align left
256  case AlignOpLeft:
257  case AlignOpDefault:
258  default:
259  x = 0;
260  y = (sizeTgt.height - height) / 2;
261  m_rectRoITgt = cvRect(x, y, width, height);
262  break;
263  }
264 }
265 
266 void WinCvIoI::transform(Mat &imgIoI, Mat &imgTgt)
267 {
268  Mat img;
269  Size dsize;
270 
271  img = Mat(imgIoI, m_rectRoIIoI);
272 
273  //
274  // Rotate IoI
275  //
276  if( m_bOpRotate )
277  {
278  warpAffine(img, imgTgt, m_matRot, m_sizeRotated, INTER_LINEAR);
279  }
280  else
281  {
282  imgTgt = img;
283  }
284 
285  //
286  // Scale IoI
287  //
288  if( m_bOpScale )
289  {
290  resize(imgTgt, imgTgt, m_sizeScaled, 0.0, 0.0, INTER_LINEAR);
291  }
292 
293  //
294  // Crop IoI
295  //
296  if( m_bOpCrop )
297  {
298  imgTgt = Mat(imgTgt, m_rectRoICropped);
299  }
300 }
301 
302 Point WinCvIoI::mapPoint(Point &ptDisplay)
303 {
304  Point pt;
305  int t;
306  double fScaleX;
307  double fScaleY;
308 
309  // adjust of image offset
310  pt.x = ptDisplay.x - m_rectRoITgt.x;
311  pt.y = ptDisplay.y - m_rectRoITgt.y;
312 
313  // point not within target image of interest
314  if( (pt.x < 0) || (pt.x >= m_rectRoITgt.width) ||
315  (pt.y < 0) || (pt.y >= m_rectRoITgt.height) )
316  {
317  pt.x = pt.y = -1;
318  return pt;
319  }
320 
321  // remap x,y relative to image of interest origin (ulc)
322  switch( m_eOpRot )
323  {
324  case RotOp270:
325  t = pt.x;
326  pt.x = pt.y + m_rectRoICropped.y;
327  pt.y = m_rectRoITgt.width - (t - m_rectRoICropped.x) - 1;
328  fScaleX = (double)(m_rectRoIIoI.width) / (double)(m_rectRoITgt.height);
329  fScaleY = (double)(m_rectRoIIoI.height) / (double)(m_rectRoITgt.width);
330  break;
331 
332  case RotOp180:
333  pt.x = m_rectRoITgt.width - pt.x - 1;
334  pt.y = m_rectRoITgt.height - pt.y - 1;
335  fScaleX = (double)(m_rectRoIIoI.width) / (double)(m_rectRoITgt.width);
336  fScaleY = (double)(m_rectRoIIoI.height) / (double)(m_rectRoITgt.height);
337  break;
338 
339  case RotOp90:
340  t = pt.x;
341  pt.x = m_rectRoITgt.height - pt.y - m_rectRoICropped.y - 1;
342  pt.y = t + m_rectRoICropped.x;
343  fScaleX = (double)(m_rectRoIIoI.width) / (double)(m_rectRoITgt.height);
344  fScaleY = (double)(m_rectRoIIoI.height) / (double)(m_rectRoITgt.width);
345  break;
346 
347  case RotOp0:
348  default:
349  fScaleX = (double)(m_rectRoIIoI.width) / (double)(m_rectRoITgt.width);
350  fScaleY = (double)(m_rectRoIIoI.height) / (double)(m_rectRoITgt.height);
351  break;
352  }
353 
354  // scale coordinate to match image of interest real size
355  pt.x = (int)((double)(pt.x) * fScaleX);
356  pt.y = (int)((double)(pt.y) * fScaleY);
357 
358  // adjust of target image of interest ROI
359  pt.x += m_rectRoIIoI.x;
360  pt.y += m_rectRoIIoI.y;
361 
362  return pt;
363 }
364 
365 Size WinCvIoI::calcMaxFit43(Size &sizeSrc, Size &sizeTgt)
366 {
367  Size sizeScaled = sizeSrc;
368 
369  // fit width into target size
370  if( sizeSrc.width > sizeTgt.width )
371  {
372  sizeScaled = ar43width(sizeTgt);
373  }
374 
375  // fit scaled-by-width height into target size
376  if( sizeScaled.height > sizeTgt.height )
377  {
378  sizeScaled = ar43height(sizeTgt);
379  }
380 
381  return sizeScaled;
382 }
180 rotation (flip verically)
Definition: Win.h:101
cv::Size ar43height(cv::Size &siz)
Calculate the nearest 4:3 aspect ratio from the height component of the target size.
Definition: WinOpenCv.h:307
RotOp
Definition: Win.h:97
RoadNarrows Robotics OpenCV Image of Interest class interface.
270 rotation (-90 &deg;)
Definition: Win.h:102
rigth alignment
Definition: Win.h:86
RoadNarrows Robotics Win abstract base class interface.
left alignment
Definition: Win.h:84
AlignOp
Definition: Win.h:81
cv::Size ar43width(cv::Size &siz)
Calculate the nearest 4:3 aspect ratio from the width component of the target size.
Definition: WinOpenCv.h:272
90 rotation
Definition: Win.h:100
0 &deg; rotation (none)
Definition: Win.h:99
RoadNarrows Robotics OpenCV Utilities.
RoadNarrows Robotics.
Definition: Camera.h:74
default alignment (left)
Definition: Win.h:83
center alignment
Definition: Win.h:85