CBICA Toolkit  1.0.0
cbicaITKOpenCVUtilities.h
Go to the documentation of this file.
1 /**
2 \file cbicaITKOpenCVUtilities.h
3 
4 \brief Some basic utility functions to be used along with OpenCV.
5 
6 Dependecies: ITK, OpenCV, OpenMP
7 
8 https://www.cbica.upenn.edu/sbia/software/ <br>
9 software@cbica.upenn.edu
10 
11 Copyright (c) 2015 University of Pennsylvania. All rights reserved. <br>
12 See COPYING file or https://www.cbica.upenn.edu/sbia/software/license.html
13 
14 */
15 #pragma once
16 
17 #include <algorithm>
18 #include <functional>
19 #ifdef _OPENMP
20 #include <omp.h>
21 #endif
22 
23 #include "itkImage.h"
24 #include "itkImageRegionIterator.h"
25 #include "gdcmMD5.h"
26 
27 #include "opencv2/core/core.hpp"
28 
29 //#include "cbicaDefinitions.h"
30 
31 //typedef itk::Image<double, 3> TImageType;
32 
33 /*
34 \namespace cbica
35 \brief Namespace for differentiating functions written for internal use
36 */
37 namespace cbica
38 {
39  /**
40  \brief Vectorizes a set of images
41 
42  \param inputSubjectsAndImages The subjects and images which are to be vectorized
43  \param maskImages The masks to be used for the input images
44  \param columnMajor If true, image intensities are converted to column vectors; otherwise they are converted to row vectors; and then they are concatinated
45  \param appendInputImagesFromSubjects If true, concatenate all image voxels together in a single column/row
46  \param maskDefinedPerSubject If true, the mask is defined on a per-subject basis instead of per-modality
47  \return An OpenCV Mat: size is [inputSubjectsAndImages[i][j]->GetLargestPossibleRegion().GetSize(), inputSubjectsAndImages[j].size()] if columnMajor is true; transpose otherwise
48  */
49  template< class TImageType
50 #if (_MSC_VER >= 1800) || (__GNUC__ > 4)
51  = itk::Image< float, 3 >
52 #endif
53  >
54  cv::Mat VectorizeImages(const std::vector< std::vector< typename TImageType::Pointer > > inputSubjectsAndImages,
55  const std::vector< typename TImageType::Pointer > maskImages,
56  const bool columnMajor, const bool appendInputImagesFromSubjects, const bool maskDefinedPerSubject)
57  {
58  if (inputSubjectsAndImages.size() != maskImages.size())
59  {
60  std::cerr << "The number of input and mask images do not match.\n";
61  exit(EXIT_FAILURE);
62  }
63  cv::Mat returnMat;
64 
65  for (size_t i = 0; i < inputSubjectsAndImages.size(); i++)
66  {
67  std::vector< float > tempMat; //tempMat is ALWAYS initialized to float because OpenCV functions are defined for float
68  for (size_t j = 0; j < inputSubjectsAndImages[i].size(); j++)
69  {
70  if (!appendInputImagesFromSubjects)
71  {
72  tempMat.clear(); // re-initialize tempMat if intensities from different modalities are not to be concatenated
73  }
74  int maskIndexToConsider = j;
75  if (maskDefinedPerSubject)
76  {
77  maskIndexToConsider = i;
78  }
79 
80  itk::ImageRegionIterator<TImageType>
81  inputImageIterator(inputSubjectsAndImages[i][j], inputSubjectsAndImages[i][j]->GetLargestPossibleRegion()),
82  maskImageIterator(maskImages[maskIndexToConsider], maskImages[maskIndexToConsider]->GetLargestPossibleRegion());
83 
84  maskImageIterator.GoToBegin();
85 
86  while (!maskImageIterator.IsAtEnd())
87  {
88  if (maskImageIterator.Get() != static_cast<typename TImageType::PixelType>(0))
89  {
90  inputImageIterator.SetIndex(maskImageIterator.GetIndex());
91  tempMat.push_back(static_cast<float>(inputImageIterator.Get()));
92  }
93  ++maskImageIterator;
94  }
95  if (!appendInputImagesFromSubjects)
96  {
97  returnMat.push_back(tempMat);
98  }
99  }
100  if (appendInputImagesFromSubjects)
101  {
102  returnMat.push_back(tempMat);
103  }
104  }
105 
106  if (columnMajor)
107  {
108  cv::transpose(returnMat, returnMat);
109  }
110  return returnMat;
111  }
112 
113  /**
114  \brief Vectorizes a set of images
115 
116  \param inputSubjectsAndImages The subjects and images which are to be vectorized
117  \param maskIndeces The mask indeces to be used for the input images
118  \param columnMajor If true, image intensities are converted to column vectors; otherwise they are converted to row vectors; and then they are concatinated
119  \param appendInputImagesFromSubjects If true, concatenate all image voxels together in a single column/row
120  \param maskDefinedPerSubject If true, the mask is defined on a per-subject basis instead of per-modality
121  \return An OpenCV Mat: size is [inputSubjectsAndImages[i][j]->GetLargestPossibleRegion().GetSize(), inputSubjectsAndImages[j].size()] if columnMajor is true; transpose otherwise
122  */
123  template< class TImageType
124 #if (_MSC_VER >= 1800) || (__GNUC__ > 4)
125  = itk::Image< float, 3 >
126 #endif
127  >
128  cv::Mat VectorizeImages(const std::vector< std::vector< typename TImageType::Pointer > > inputSubjectsAndImages,
129  const std::vector< std::vector< typename TImageType::IndexType > > maskIndeces,
130  const bool appendInputImagesFromSubjects = false, const bool columnMajor = false, const bool maskDefinedPerSubject = false)
131  {
132  if (maskDefinedPerSubject)
133  {
134  if (inputSubjectsAndImages.size() != maskIndeces.size())
135  {
136  std::cerr << "The number of input and mask images do not match.\n";
137  exit(EXIT_FAILURE);
138  }
139  }
140  else
141  {
142  if (inputSubjectsAndImages[0].size() != maskIndeces.size())
143  {
144  std::cerr << "The number of input and mask images do not match.\n";
145  exit(EXIT_FAILURE);
146  }
147  }
148  cv::Mat returnMat; // pre-allocate this and then parallelize the next big i-loop
149 
150  for (size_t i = 0; i < inputSubjectsAndImages.size(); i++)
151  {
152  cv::Mat tempMat; //tempMat is ALWAYS initialized to float because OpenCV functions are defined for float
153  for (size_t j = 0; j < inputSubjectsAndImages[i].size(); j++)
154  {
155  if (!appendInputImagesFromSubjects)
156  {
157  tempMat.empty(); // re-initialize tempMat if intensities from different modalities are not to be concatenated
158  }
159  itk::ImageRegionIterator<TImageType>
160  inputImageIterator(inputSubjectsAndImages[i][j], inputSubjectsAndImages[i][j]->GetLargestPossibleRegion());
161 
162  int maskIndexToConsider = j;
163  if (maskDefinedPerSubject)
164  {
165  maskIndexToConsider = i;
166  }
167  for (size_t k = 0; k < maskIndeces[maskIndexToConsider].size(); k++)
168  {
169  inputImageIterator.SetIndex(maskIndeces[maskIndexToConsider][k]);
170  tempMat.push_back(static_cast<float>(inputImageIterator.Get()));
171  }
172  if (!appendInputImagesFromSubjects)
173  {
174  returnMat.push_back(tempMat.t());
175  }
176  }
177  if (appendInputImagesFromSubjects)
178  {
179  returnMat.push_back(tempMat.t());
180  }
181  }
182 
183  if (columnMajor)
184  {
185  return returnMat.t();
186  }
187  return returnMat;
188  }
189 
190  /**
191  \brief Vectorizes a set of images
192 
193  \param inputSubjectsAndImages The images which are to be vectorized
194  \param columnMajor If true, image intensities are converted to column vectors; otherwise they are converted to row vectors; and then they are concatinated
195  \param appendInputImagesFromSubjects If true, concatenate all image voxels together in a single column/row
196  \return An OpenCV Mat: size is [inputSubjectsAndImages[i]->GetLargestPossibleRegion().GetSize(), inputSubjectsAndImages.size()] if columnMajor is true; transpose otherwise
197  */
198  template< class TImageType
199 #if (_MSC_VER >= 1800) || (__GNUC__ > 4)
200  = itk::Image< float, 3 >
201 #endif
202  >
203  cv::Mat VectorizeImages(const std::vector< std::vector< typename TImageType::Pointer > > inputSubjectsAndImages,
204  const bool columnMajor = false, const bool appendInputImagesFromSubjects = false)
205  {
206  cv::Mat returnMat; // pre-allocate this and then parallelize the next big i-loop
207 
208  for (size_t i = 0; i < inputSubjectsAndImages.size(); i++)
209  {
210  std::vector< float > tempMat; //tempMat is ALWAYS initialized to float because OpenCV functions are defined for float
211  for (size_t j = 0; j < inputSubjectsAndImages[i].size(); j++)
212  {
213  if (!appendInputImagesFromSubjects)
214  {
215  tempMat.clear(); // re-initialize tempMat if intensities from different modalities are not to be concatenated
216  }
217  itk::ImageRegionIterator<TImageType>
218  inputImageIterator(inputSubjectsAndImages[i][j], inputSubjectsAndImages[i][j]->GetLargestPossibleRegion());
219 
220  while (!inputImageIterator.IsAtEnd())
221  {
222  // should there be a check put here regarding loads of zero-intensities for images that don't have any mask?
223  tempMat.push_back(static_cast<float>(inputImageIterator.Get()));
224  ++inputImageIterator;
225  }
226  if (!appendInputImagesFromSubjects)
227  {
228  returnMat.push_back(tempMat);
229  }
230  }
231  if (appendInputImagesFromSubjects)
232  {
233  returnMat.push_back(tempMat);
234  }
235  }
236 
237  if (columnMajor)
238  {
239  cv::transpose(returnMat, returnMat);
240  }
241  return returnMat;
242  }
243 
244  /**
245  \brief Normalize a vector based on its L2 norm
246 
247  \param inputVector The vector to normalize
248  \return The normalized vector
249  */
250  template< typename TDataType
251 #if (_MSC_VER >= 1800) || (__GNUC__ > 4)
252  = double
253 #endif
254  >
255  std::vector< TDataType > L2normalize(const std::vector< TDataType > &inputVector)
256  {
257  std::vector< TDataType > returnVector;
258  float norm = cv::norm(inputVector, cv::NORM_L2);
259  if (norm == 0)
260  {
261  std::cerr << "Calculated norm = 0, please check data.\n";
262  exit(EXIT_FAILURE);
263  }
264  returnVector.resize(inputVector.size());
265  std::transform(inputVector.begin(), inputVector.end(), returnVector.begin(), std::bind1st(std::divides< float >(), norm));
266 
267  return returnVector;
268  }
269 
270  /**
271  \brief Wrap of OpenCV's multiply function
272  */
273  cv::Mat Multiply(const cv::Mat &input1, const cv::Mat &input2)
274  {
275  cv::Mat returnMat;
276  cv::multiply(input1, input2, returnMat);
277  return returnMat;
278  }
279 
280  /**
281  \brief Wrap of OpenCV's multiply function
282  */
283  cv::Mat Multiply(const cv::Mat &input1, const double input2)
284  {
285  cv::Mat returnMat;
286  cv::multiply(input1, input2, returnMat);
287  return returnMat;
288  }
289 
290  /**
291  \brief Wrap of OpenCV's add function
292  */
293  cv::Mat Add(const cv::InputArray &input1, const cv::InputArray &input2)
294  {
295  cv::Mat returnMat;
296  cv::add(input1, input2, returnMat);
297  return returnMat;
298  }
299 
300  /**
301  \brief Wrap of OpenCV's invert function
302  */
303  cv::Mat Invert(const cv::InputArray &input)
304  {
305  cv::Mat returnMat;
306  cv::invert(input, returnMat);
307  return returnMat;
308  }
309 
310  /**
311  \brief Wrap of OpenCV's transpose function
312  */
313  cv::Mat Transpose(const cv::InputArray &input)
314  {
315  cv::Mat returnMat;
316  cv::transpose(input, returnMat);
317  return returnMat;
318  }
319 
320  /**
321  \brief Wrap of OpenCV's subtract function
322  */
323  cv::Mat Subtract(const cv::InputArray &input1, const cv::InputArray &input2)
324  {
325  cv::Mat returnMat;
326  cv::subtract(input1, input2, returnMat);
327  return returnMat;
328  }
329 }
cv::Mat Add(const cv::InputArray &input1, const cv::InputArray &input2)
Wrap of OpenCV's add function.
Definition: cbicaITKOpenCVUtilities.h:293
cv::Mat Transpose(const cv::InputArray &input)
Wrap of OpenCV's transpose function.
Definition: cbicaITKOpenCVUtilities.h:313
cv::Mat VectorizeImages(const std::vector< std::vector< typename TImageType::Pointer > > inputSubjectsAndImages, const std::vector< typename TImageType::Pointer > maskImages, const bool columnMajor, const bool appendInputImagesFromSubjects, const bool maskDefinedPerSubject)
Vectorizes a set of images.
Definition: cbicaITKOpenCVUtilities.h:54
cv::Mat Subtract(const cv::InputArray &input1, const cv::InputArray &input2)
Wrap of OpenCV's subtract function.
Definition: cbicaITKOpenCVUtilities.h:323
std::vector< TDataType > L2normalize(const std::vector< TDataType > &inputVector)
Normalize a vector based on its L2 norm.
Definition: cbicaITKOpenCVUtilities.h:255
cv::Mat Invert(const cv::InputArray &input)
Wrap of OpenCV's invert function.
Definition: cbicaITKOpenCVUtilities.h:303
cv::Mat Multiply(const cv::Mat &input1, const cv::Mat &input2)
Wrap of OpenCV's multiply function.
Definition: cbicaITKOpenCVUtilities.h:273