OpenCVUtil.cpp
Go to the documentation of this file.
1#include "OpenCVUtil.h"
2
3#include <cstring>
4
6
7#include <VisionX/interface/components/Calibration.h>
8
9#include <Image/ByteImage.h>
10
11void
12visionx::copyCvMatToIVT(cv::Mat const& input, CByteImage* output)
13{
14 ARMARX_CHECK_NOT_NULL(input.data);
16 ARMARX_CHECK_EXPRESSION(input.isContinuous());
17 ARMARX_CHECK_EQUAL(int(input.elemSize()), output->bytesPerPixel);
18
19 int imageSize = output->width * output->height * output->bytesPerPixel;
20 ARMARX_CHECK_EQUAL(int(input.total() * input.elemSize()), imageSize);
21
22 std::memcpy(output->pixels, input.data, imageSize);
23}
24
25void
26visionx::copyCvDepthToGrayscaleIVT(cv::Mat const& inputInMeters, CByteImage* output)
27{
28 ARMARX_CHECK_NOT_NULL(inputInMeters.data);
30 ARMARX_CHECK_EQUAL(inputInMeters.type(), CV_32FC1);
31 ARMARX_CHECK_EQUAL(output->type, CByteImage::eRGB24);
32 ARMARX_CHECK_EQUAL(inputInMeters.rows, output->height);
33 ARMARX_CHECK_EQUAL(inputInMeters.cols, output->width);
34
35 uchar* outRow = output->pixels;
36 int outStride = 3 * output->width;
37
38 double minD, maxD;
39 cv::minMaxLoc(inputInMeters, &minD, &maxD);
40
41 float invRangeD = 1.0 / (maxD - minD);
42
43 for (int y = 0; y < inputInMeters.rows; ++y)
44 {
45 float const* depthRow = inputInMeters.ptr<float>(y);
46 for (int x = 0; x < inputInMeters.cols; ++x)
47 {
48 float depth = depthRow[x];
49 float normalizedDepth = (depth - minD) * invRangeD;
50 int pixelValue = std::floor(255.0f - 255.0f * normalizedDepth);
51
52 outRow[3 * x + 0] = pixelValue;
53 outRow[3 * x + 1] = pixelValue;
54 outRow[3 * x + 2] = pixelValue;
55 }
56
57 outRow += outStride;
58 }
59}
60
61cv::Mat
63{
65 ARMARX_CHECK_EQUAL(input->type, CByteImage::eRGB24);
66
67 int width = input->width;
68 int height = input->height;
69 cv::Mat result(height, width, CV_32FC1);
70
71 convertWeirdArmarXToDepthInMeters(input->pixels, result);
72
73 return result;
74}
75
76void
77visionx::convertWeirdArmarXToDepthInMeters(const uint8_t* input, cv::Mat& output)
78{
79 ARMARX_CHECK_EQUAL(output.type(), CV_32FC1);
80
81 const unsigned char* inputRow = input;
82 for (int row = 0; row < output.rows; ++row)
83 {
84 float* outputRow = output.ptr<float>(row);
85 for (int col = 0; col < output.cols; ++col)
86 {
87 // Depth is stored in mm (lower 8 bits in r, higher 8 bits g)
88 int r = inputRow[col * 3 + 0];
89 int g = inputRow[col * 3 + 1];
90 int depthInMM = (g << 8) + r;
91 outputRow[col] = static_cast<float>(depthInMM) / 1000.0f;
92 }
93
94 inputRow += output.cols * 3;
95 }
96}
97
98void
99visionx::convertDepthInMetersToWeirdArmarX(const cv::Mat& input, CByteImage* output)
100{
101 ARMARX_CHECK_NOT_NULL(output);
102 ARMARX_CHECK_EQUAL(output->type, CByteImage::eRGB24);
103 ARMARX_CHECK_EQUAL(output->width, input.cols);
104 ARMARX_CHECK_EQUAL(output->height, input.rows);
105 ARMARX_CHECK_EQUAL(CV_32FC1, input.type());
106
107 const auto height = output->height;
108 const auto width = output->width;
109
110 unsigned char* outputRow = output->pixels;
111 for (int y = 0; y < height; ++y)
112 {
113 const float* inputRow = input.ptr<float>(y);
114 for (int x = 0; x < width; ++x)
115 {
116 const auto depthInMM = inputRow[x] * 1000;
117 // Depth is stored in mm (lower 8 bits in r, higher 8 bits g)
118 outputRow[x * 3 + 0] = static_cast<unsigned char>(std::fmod(depthInMM, 256));
119 outputRow[x * 3 + 1] = static_cast<unsigned char>(std::fmod(depthInMM / 256, 256));
120 outputRow[x * 3 + 2] =
121 static_cast<unsigned char>(std::fmod(depthInMM / 256 / 256, 256));
122 }
123
124 inputRow += width * 3;
125 }
126}
127
128namespace detail
129{
130 template <typename Float>
131 void
132 fillEmptyValues(cv::Mat& output)
133 {
134 output.at<Float>(0, 1) = 0;
135 output.at<Float>(1, 0) = 0;
136 output.at<Float>(2, 0) = 0;
137 output.at<Float>(2, 1) = 0;
138 output.at<Float>(2, 2) = 1;
139 }
140
141 void
142 checkFloatMatrix(const cv::Mat& matrix, const std::string& semanticName)
143 {
144 if (!(matrix.depth() == CV_32F || matrix.depth() == CV_64F))
145 {
146 std::stringstream ss;
147 ss << "Passed " << semanticName << " must be floating point type, "
148 << "i.e. CV_32F (" << CV_32F << ") or CV_64F (" << CV_64F << "), "
149 << "but its type was " << matrix.type() << ".";
150 throw std::invalid_argument(ss.str());
151 }
152 }
153
154 void
155 checkCameraMatrix(const cv::Mat& matrix)
156 {
157 checkFloatMatrix(matrix, "camera matrix");
158 ARMARX_CHECK_GREATER_EQUAL(matrix.rows, 3);
159 ARMARX_CHECK_GREATER_EQUAL(matrix.cols, 3);
160 }
161
162 template <typename Float>
163 void
164 fillCameraMatrix(const CCalibration::CCameraParameters& ivtCameraParameters, cv::Mat& output)
165 {
166 checkCameraMatrix(output);
167
169
170 output.at<Float>(0, 0) = Float(ivtCameraParameters.focalLength.x);
171 output.at<Float>(0, 2) = Float(ivtCameraParameters.principalPoint.x);
172 output.at<Float>(1, 1) = Float(ivtCameraParameters.focalLength.y);
173 output.at<Float>(1, 2) = Float(ivtCameraParameters.principalPoint.y);
174 }
175
176 template <typename Float>
177 void
178 fillCameraMatrix(const visionx::CameraParameters& cameraParams, cv::Mat& output)
179 {
180 checkCameraMatrix(output);
181
182 ARMARX_CHECK_EQUAL(cameraParams.focalLength.size(), 2);
183 ARMARX_CHECK_EQUAL(cameraParams.principalPoint.size(), 2);
184
185 const float nodalPointX = cameraParams.principalPoint.at(0);
186 const float nodalPointY = cameraParams.principalPoint.at(1);
187 const float focalLengthX = cameraParams.focalLength.at(0);
188 const float focalLengthY = cameraParams.focalLength.at(1);
189
191
192 output.at<Float>(0, 0) = Float(focalLengthX);
193 output.at<Float>(0, 2) = Float(nodalPointX);
194 output.at<Float>(1, 1) = Float(focalLengthY);
195 output.at<Float>(1, 2) = Float(nodalPointY);
196 }
197
198} // namespace detail
199
200void
201visionx::fillCameraMatrix(const visionx::CameraParameters& cameraParams, cv::Mat& output)
202{
204 if (output.depth() == CV_32F)
205 {
206 detail::fillCameraMatrix<float>(cameraParams, output);
207 }
208 else if (output.depth() == CV_64F)
209 {
210 detail::fillCameraMatrix<double>(cameraParams, output);
211 }
212}
213
214void
215visionx::fillCameraMatrix(const CCalibration::CCameraParameters& ivtCameraParameters,
216 cv::Mat& output)
217{
219 if (output.depth() == CV_32F)
220 {
221 detail::fillCameraMatrix<float>(ivtCameraParameters, output);
222 }
223 else if (output.depth() == CV_64F)
224 {
225 detail::fillCameraMatrix<double>(ivtCameraParameters, output);
226 }
227}
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK_GREATER_EQUAL(lhs, rhs)
This macro evaluates whether lhs is greater or equal (>=) rhs and if it turns out to be false it will...
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
This file offers overloads of toIce() and fromIce() functions for STL container types.
void checkFloatMatrix(const cv::Mat &matrix, const std::string &semanticName)
void checkCameraMatrix(const cv::Mat &matrix)
void fillEmptyValues(cv::Mat &output)
void fillCameraMatrix(const CCalibration::CCameraParameters &ivtCameraParameters, cv::Mat &output)
void convertDepthInMetersToWeirdArmarX(const cv::Mat &input, CByteImage *output)
cv::Mat convertWeirdArmarXToDepthInMeters(CByteImage const *input)
Convert ArmarX encoding of depth information in an RGB image to depth in meters.
void copyCvDepthToGrayscaleIVT(cv::Mat const &inputInMeters, CByteImage *output)
Copies a floating point depth image (in meters) to an RGB depth representation.
void fillCameraMatrix(const visionx::CameraParameters &cameraParams, cv::Mat &output)
Fill a propertly initialized camera matrix with the given camera parameters.
void copyCvMatToIVT(cv::Mat const &input, CByteImage *output)
Copies the contents of an OpenCV matrix to an IVT CByteImage.