OSVR-Core
cvUtils.h
Go to the documentation of this file.
1 
11 // Copyright 2016 Sensics, Inc.
12 //
13 // Licensed under the Apache License, Version 2.0 (the "License");
14 // you may not use this file except in compliance with the License.
15 // You may obtain a copy of the License at
16 //
17 // http://www.apache.org/licenses/LICENSE-2.0
18 //
19 // Unless required by applicable law or agreed to in writing, software
20 // distributed under the License is distributed on an "AS IS" BASIS,
21 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 // See the License for the specific language governing permissions and
23 // limitations under the License.
24 
25 #ifndef INCLUDED_cvUtils_h_GUID_65B004C2_722B_4BBF_4EC7_05B2AD861254
26 #define INCLUDED_cvUtils_h_GUID_65B004C2_722B_4BBF_4EC7_05B2AD861254
27 
28 // Internal Includes
29 #include <BlobExtractor.h>
30 
31 // Library/third-party includes
32 #include <opencv2/core/core.hpp>
33 #include <opencv2/imgproc/imgproc.hpp>
34 
35 // Standard includes
36 #include <cstdint>
37 #include <random>
38 #include <utility>
39 #include <vector>
40 
41 namespace osvr {
42 namespace vbtracker {
43  inline cv::Point2f castPointToFloat(cv::Point2d const &p) {
44  return cv::Point2f(static_cast<float>(p.x), static_cast<float>(p.y));
45  }
46 
47  inline void drawSubpixelPoint(cv::Mat image, cv::Point2d point,
48  cv::Scalar color = cv::Scalar(0, 0, 0),
49  double radius = 1.,
50  std::uint8_t fractionalBits = 3) {
51  const auto SHIFT = std::pow(2, fractionalBits);
52  auto intPoint = cv::Point(static_cast<int>(point.x * SHIFT),
53  static_cast<int>(point.y * SHIFT));
54  cv::circle(image, intPoint, static_cast<int>(radius * SHIFT), color, -1,
55  8, fractionalBits);
56  }
57 
75  template <typename F>
77  cv::Mat const &baseImage, std::vector<ContourType> const &contours,
78  F &&colorFunc, bool fillContours = false, double centerDotRadius = 1.2,
79  bool colorCenterDot = true) {
80  cv::Mat highlightedContours;
81  if (baseImage.channels() > 1) {
82  highlightedContours = baseImage.clone();
83  } else {
84  cv::cvtColor(baseImage, highlightedContours, cv::COLOR_GRAY2BGR);
85  }
86  const cv::Scalar black(0, 0, 0);
87  const std::size_t n = contours.size();
88  for (std::size_t i = 0; i < n; ++i) {
89  cv::Scalar color = std::forward<F>(colorFunc)(contours[i], i);
90  cv::drawContours(highlightedContours, contours, i, color,
91  fillContours ? -1 : 1);
92 
93  if (!fillContours) {
95  auto data = getContourBasicDetails(contours[i]);
96  drawSubpixelPoint(highlightedContours, data.center,
97  colorCenterDot ? color : black,
98  centerDotRadius);
99  }
100  }
101  return highlightedContours;
102  }
103 
120  inline cv::Mat drawColoredContours(cv::Mat const &baseImage,
121  std::vector<ContourType> const &contours,
122  bool deterministic = true,
123  bool fillContours = false,
124  double centerDotRadius = 1.2,
125  bool colorCenterDot = true) {
126  // Using a deterministic 32-bit seed here, so we get the same colors in
127  // each call - by default.
128  std::mt19937 mt(31415);
129  if (!deterministic) {
130  // If you didn't want deterministic, ok, we'll go get the random
131  // device and seed it.
132  std::random_device rd;
133  mt.seed(rd());
134  }
135 
136  // std::uniform_int_distribution<int> colorDist(0, 255);
138  auto colorDist = [](std::mt19937 &mt) { return mt() & 0xff; };
140  baseImage, contours,
141  [&](ContourType const &, std::size_t) {
142  return cv::Scalar(colorDist(mt), colorDist(mt), colorDist(mt));
143  },
144  fillContours, centerDotRadius, colorCenterDot);
145  }
146 
164  cv::Mat const &baseImage, std::vector<ContourType> const &contours,
165  cv::Scalar color, bool fillContours = false,
166  double centerDotRadius = 1.2, bool colorCenterDot = true) {
168  baseImage, contours,
169  [&color](ContourType const &, std::size_t) { return color; },
170  fillContours, centerDotRadius, colorCenterDot);
171  }
174  enum {
175  HIERARCHY_NEXT_SIBLING_CONTOUR = 0,
176  HIERARCHY_PREV_SIBLING_CONTOUR = 1,
177  HIERARCHY_FIRST_CHILD_CONTOUR = 2,
178  HIERARCHY_PARENT_CONTOUR = 3,
179  };
180 
181  template <typename F>
182  std::vector<ContourType>
183  getOutsidesOfConnectedComponents(cv::Mat input, F &&additionalPredicate) {
184  std::vector<ContourType> contours;
185  std::vector<cv::Vec4i> hierarchy;
186  cv::findContours(input, contours, hierarchy, cv::RETR_CCOMP,
187  cv::CHAIN_APPROX_NONE);
188  // intentionally storing in int, instead of auto, since we'll compare
189  // against int.
190  int n = static_cast<int>(contours.size());
191  std::vector<ContourType> ret;
192  for (std::size_t i = 0; i < n; ++i) {
193  // If this contour has no parent, then it's the outer contour of a
194  // connected component
195  if (hierarchy[i][HIERARCHY_PARENT_CONTOUR] < 0 &&
196  std::forward<F>(additionalPredicate)(contours[i])) {
197  ret.emplace_back(std::move(contours[i]));
198  }
199  }
200  return ret;
201  }
202 
207  template <typename F>
209  cv::InputOutputArray input,
210  std::vector<ContourType> &contoursTempStorage,
211  std::vector<cv::Vec4i> &hierarchyTempStorage, F &&continuation) {
212  cv::findContours(input, contoursTempStorage, hierarchyTempStorage,
213  cv::RETR_CCOMP, cv::CHAIN_APPROX_NONE);
214  // intentionally storing in int, instead of auto, since we'll compare
215  // against int.
216  int n = static_cast<int>(contoursTempStorage.size());
218  for (int outsides = 0; outsides >= 0 && outsides < n;
219  outsides = hierarchyTempStorage[outsides]
220  [HIERARCHY_NEXT_SIBLING_CONTOUR]) {
221  for (int idx = hierarchyTempStorage[outsides]
222  [HIERARCHY_FIRST_CHILD_CONTOUR];
223  idx >= 0 && idx < n;
224  idx =
225  hierarchyTempStorage[idx][HIERARCHY_NEXT_SIBLING_CONTOUR])
227  std::forward<F>(continuation)(
228  std::move(contoursTempStorage[idx]));
229  }
230  }
232  template <typename F>
233  inline void consumeHolesOfConnectedComponents(cv::InputOutputArray input,
234  F &&continuation) {
235  std::vector<ContourType> contours;
236  std::vector<cv::Vec4i> hierarchy;
237  consumeHolesOfConnectedComponents(input, contours, hierarchy,
238  std::forward<F>(continuation));
239  }
240 } // namespace vbtracker
241 } // namespace osvr
242 
243 #endif // INCLUDED_cvUtils_h_GUID_65B004C2_722B_4BBF_4EC7_05B2AD861254
cv::Mat drawColoredContours(cv::Mat const &baseImage, std::vector< ContourType > const &contours, bool deterministic=true, bool fillContours=false, double centerDotRadius=1.2, bool colorCenterDot=true)
Draw contours on a copy of the base image (converted to BGR, if required), with each contour a unique...
Definition: cvUtils.h:120
The main namespace for all C++ elements of the framework, internal and external.
Definition: namespace_osvr.dox:3
void consumeHolesOfConnectedComponents(cv::InputOutputArray input, std::vector< ContourType > &contoursTempStorage, std::vector< cv::Vec4i > &hierarchyTempStorage, F &&continuation)
Calls a continuation on every hole of a connected component.
Definition: cvUtils.h:208
cv::Mat drawFunctorColoredContours(cv::Mat const &baseImage, std::vector< ContourType > const &contours, F &&colorFunc, bool fillContours=false, double centerDotRadius=1.2, bool colorCenterDot=true)
Draw contours on a copy of the base image (converted to BGR, if required), with each contour a potent...
Definition: cvUtils.h:76
cv::Mat drawSingleColoredContours(cv::Mat const &baseImage, std::vector< ContourType > const &contours, cv::Scalar color, bool fillContours=false, double centerDotRadius=1.2, bool colorCenterDot=true)
Draw contours on a copy of the base image (converted to BGR, if required), with all contours the same...
Definition: cvUtils.h:163
double Scalar
Common scalar type.
Definition: FlexibleKalmanBase.h:48