Visual Servoing Platform  version 3.6.1 under development (2025-01-14)
vpImageConvert_opencv.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Convert image types.
32  *
33 *****************************************************************************/
34 
39 #include <visp3/core/vpConfig.h>
40 #include <visp3/core/vpImageConvert.h>
41 
42 #if defined(VISP_HAVE_SIMDLIB)
43 #include <Simd/SimdLib.h>
44 #endif
45 
46 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
47 
48 BEGIN_VISP_NAMESPACE
93 void vpImageConvert::convert(const cv::Mat &src, vpImage<vpRGBa> &dest, bool flip)
94 {
95  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
96  unsigned int destRows = dest.getRows();
97  unsigned int destCols = dest.getCols();
98  const unsigned int index_0 = 0;
99  const unsigned int index_1 = 1;
100  const unsigned int index_2 = 2;
101  const unsigned int index_3 = 3;
102  if (src.type() == CV_8UC4) {
103  vpRGBa rgbaVal;
104  for (unsigned int i = 0; i < destRows; ++i)
105  for (unsigned int j = 0; j < destCols; ++j) {
106  cv::Vec4b tmp = src.at<cv::Vec4b>(static_cast<int>(i), static_cast<int>(j));
107  rgbaVal.R = tmp[index_2];
108  rgbaVal.G = tmp[index_1];
109  rgbaVal.B = tmp[index_0];
110  rgbaVal.A = tmp[index_3];
111  if (flip) {
112  dest[destRows - i - 1][j] = rgbaVal;
113  }
114  else {
115  dest[i][j] = rgbaVal;
116  }
117  }
118  }
119  else if (src.type() == CV_8UC3) {
120 #if defined(VISP_HAVE_SIMDLIB)
121  if (src.isContinuous() && (!flip)) {
122  SimdRgbToBgra(src.data, src.cols, src.rows, src.step[0], reinterpret_cast<uint8_t *>(dest.bitmap),
123  dest.getWidth() * sizeof(vpRGBa), vpRGBa::alpha_default);
124  }
125  else {
126 #endif
127  vpRGBa rgbaVal;
128  rgbaVal.A = vpRGBa::alpha_default;
129  for (unsigned int i = 0; i < destRows; ++i) {
130  for (unsigned int j = 0; j < destCols; ++j) {
131  cv::Vec3b tmp = src.at<cv::Vec3b>(static_cast<int>(i), static_cast<int>(j));
132  rgbaVal.R = tmp[index_2];
133  rgbaVal.G = tmp[index_1];
134  rgbaVal.B = tmp[index_0];
135  if (flip) {
136  dest[destRows - i - 1][j] = rgbaVal;
137  }
138  else {
139  dest[i][j] = rgbaVal;
140  }
141  }
142  }
143 #if defined(VISP_HAVE_SIMDLIB)
144  }
145 #endif
146  }
147  else if (src.type() == CV_8UC1) {
148 #if defined(VISP_HAVE_SIMDLIB)
149  if (src.isContinuous() && (!flip)) {
150  SimdGrayToBgra(src.data, src.cols, src.rows, src.step[0], reinterpret_cast<uint8_t *>(dest.bitmap),
151  dest.getWidth() * sizeof(vpRGBa), vpRGBa::alpha_default);
152  }
153  else {
154 #endif
155  vpRGBa rgbaVal;
156  for (unsigned int i = 0; i < destRows; ++i) {
157  for (unsigned int j = 0; j < destCols; ++j) {
158  rgbaVal = src.at<unsigned char>(static_cast<int>(i), static_cast<int>(j));
159  rgbaVal.A = vpRGBa::alpha_default;
160  if (flip) {
161  dest[destRows - i - 1][j] = rgbaVal;
162  }
163  else {
164  dest[i][j] = rgbaVal;
165  }
166  }
167  }
168 #if defined(VISP_HAVE_SIMDLIB)
169  }
170 #endif
171  }
172 }
173 
213 void vpImageConvert::convert(const cv::Mat &src, vpImage<unsigned char> &dest, bool flip, unsigned int nThreads)
214 {
215  if (src.type() == CV_8UC1) {
216  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
217  unsigned int destRows = dest.getRows();
218  unsigned int destCols = dest.getCols();
219  if (src.isContinuous() && (!flip)) {
220  memcpy(dest.bitmap, src.data, static_cast<size_t>(src.rows * src.cols));
221  }
222  else {
223  if (flip) {
224  for (unsigned int i = 0; i < destRows; ++i) {
225  memcpy(dest.bitmap + (i * destCols), src.data + ((destRows - i - 1) * src.step1()), static_cast<size_t>(src.step));
226  }
227  }
228  else {
229  for (unsigned int i = 0; i < destRows; ++i) {
230  memcpy(dest.bitmap + (i * destCols), src.data + (i * src.step1()), static_cast<size_t>(src.step));
231  }
232  }
233  }
234  }
235  else if (src.type() == CV_8UC3) {
236  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
237  unsigned int destRows = dest.getRows();
238  unsigned int destCols = dest.getCols();
239  if (src.isContinuous()) {
240  BGRToGrey((unsigned char *)src.data, (unsigned char *)dest.bitmap, static_cast<unsigned int>(src.cols), static_cast<unsigned int>(src.rows),
241  flip, nThreads);
242  }
243  else {
244  if (flip) {
245  for (unsigned int i = 0; i < destRows; ++i) {
246  BGRToGrey((unsigned char *)src.data + (i * src.step1()),
247  (unsigned char *)dest.bitmap + ((destRows - i - 1) * destCols),
248  static_cast<unsigned int>(destCols), 1, false);
249  }
250  }
251  else {
252  for (unsigned int i = 0; i < destRows; ++i) {
253  BGRToGrey((unsigned char *)src.data + (i * src.step1()), (unsigned char *)dest.bitmap + (i * destCols),
254  static_cast<unsigned int>(destCols), 1, false);
255  }
256  }
257  }
258  }
259  else if (src.type() == CV_8UC4) {
260  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
261  unsigned int destRows = dest.getRows();
262  unsigned int destCols = dest.getCols();
263  if (src.isContinuous()) {
264  BGRaToGrey((unsigned char *)src.data, (unsigned char *)dest.bitmap, static_cast<unsigned int>(src.cols),
265  static_cast<unsigned int>(src.rows), flip, nThreads);
266  }
267  else {
268  if (flip) {
269  for (unsigned int i = 0; i < destRows; ++i) {
270  BGRaToGrey((unsigned char *)src.data + (i * src.step1()),
271  (unsigned char *)dest.bitmap + ((destRows - i - 1) * destCols),
272  static_cast<unsigned int>(destCols), 1, false);
273  }
274  }
275  else {
276  for (unsigned int i = 0; i < destRows; ++i) {
277  BGRaToGrey((unsigned char *)src.data + (i * src.step1()), (unsigned char *)dest.bitmap + (i * destCols),
278  static_cast<unsigned int>(destCols), 1, false);
279  }
280  }
281  }
282  }
283 }
284 
292 void vpImageConvert::convert(const cv::Mat &src, vpImage<float> &dest, bool flip)
293 {
294  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
295  unsigned int destRows = dest.getRows();
296  unsigned int destCols = dest.getCols();
297 
298  if (src.type() == CV_32FC1) {
299  for (unsigned int i = 0; i < destRows; ++i) {
300  for (unsigned int j = 0; j < destCols; ++j) {
301  if (flip) {
302  dest[dest.getRows() - i - 1][j] = src.at<float>(static_cast<int>(i), static_cast<int>(j));
303  }
304  else {
305  dest[i][j] = src.at<float>(static_cast<int>(i), static_cast<int>(j));
306  }
307  }
308  }
309  }
310  else if (src.type() == CV_16SC1) {
311  for (unsigned int i = 0; i < destRows; ++i) {
312  for (unsigned int j = 0; j < destCols; ++j) {
313  if (flip) {
314  dest[dest.getRows() - i - 1][j] = src.at<short>(static_cast<int>(i), static_cast<int>(j));
315  }
316  else {
317  dest[i][j] = src.at<short>(static_cast<int>(i), static_cast<int>(j));
318  }
319  }
320  }
321  }
322  else {
323  throw vpException(vpException::badValue, "cv::Mat type is not supported!");
324  }
325 }
326 
334 void vpImageConvert::convert(const cv::Mat &src, vpImage<double> &dest, bool flip)
335 {
336  vpImage<float> I_float;
337  convert(src, I_float, flip);
338  unsigned int nbRows = static_cast<unsigned int>(src.rows);
339  unsigned int nbCols = static_cast<unsigned int>(src.cols);
340  dest.resize(nbRows, nbCols);
341  for (unsigned int i = 0; i < nbRows; ++i) {
342  for (unsigned int j = 0; j < nbCols; ++j) {
343  dest[i][j] = I_float[i][j];
344  }
345  }
346 }
347 
355 void vpImageConvert::convert(const cv::Mat &src, vpImage<uint16_t> &dest, bool flip)
356 {
357  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
358  unsigned int destRows = dest.getRows();
359  unsigned int destCols = dest.getCols();
360 
361  if (src.type() == CV_16UC1) {
362  if (src.isContinuous()) {
363  memcpy(dest.bitmap, src.data, static_cast<size_t>(src.rows * src.cols) * sizeof(uint16_t));
364  }
365  else {
366  if (flip) {
367  for (unsigned int i = 0; i < destRows; ++i) {
368  memcpy(dest.bitmap + (i * destCols), src.data + ((destRows - i - 1) * src.step1() * sizeof(uint16_t)), static_cast<size_t>(src.step));
369  }
370  }
371  else {
372  for (unsigned int i = 0; i < destRows; ++i) {
373  memcpy(dest.bitmap + (i * destCols), src.data + (i * src.step1() * sizeof(uint16_t)), static_cast<size_t>(src.step));
374  }
375  }
376  }
377  }
378  else {
379  throw(vpException(vpException::fatalError, "cv:Mat format not supported for conversion into vpImage<uint16_t>"));
380  }
381 }
382 
390 void vpImageConvert::convert(const cv::Mat &src, vpImage<vpRGBf> &dest, bool flip)
391 {
392  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
393  unsigned int destRows = dest.getRows();
394  unsigned int destCols = dest.getCols();
395  const unsigned int index_0 = 0;
396  const unsigned int index_1 = 1;
397  const unsigned int index_2 = 2;
398 
399  if (src.type() == CV_32FC3) {
400  vpRGBf rgbVal;
401  for (unsigned int i = 0; i < destRows; ++i)
402  for (unsigned int j = 0; j < destCols; ++j) {
403  cv::Vec3f tmp = src.at<cv::Vec3f>(static_cast<int>(i), static_cast<int>(j));
404  rgbVal.R = tmp[index_2];
405  rgbVal.G = tmp[index_1];
406  rgbVal.B = tmp[index_0];
407  if (flip) {
408  dest[destRows - i - 1][j] = rgbVal;
409  }
410  else {
411  dest[i][j] = rgbVal;
412  }
413  }
414  }
415  else {
416  throw vpException(vpException::badValue, "cv::Mat type is not supported!");
417  }
418 }
419 
460 void vpImageConvert::convert(const vpImage<vpRGBa> &src, cv::Mat &dest)
461 {
462  cv::Mat vpToMat(static_cast<int>(src.getRows()), static_cast<int>(src.getCols()), CV_8UC4, (void *)src.bitmap);
463  cv::cvtColor(vpToMat, dest, cv::COLOR_RGBA2BGR);
464 }
465 
508 void vpImageConvert::convert(const vpImage<unsigned char> &src, cv::Mat &dest, bool copyData)
509 {
510  if (copyData) {
511  cv::Mat tmpMap(static_cast<int>(src.getRows()), static_cast<int>(src.getCols()), CV_8UC1, (void *)src.bitmap);
512  dest = tmpMap.clone();
513  }
514  else {
515  dest = cv::Mat(static_cast<int>(src.getRows()), static_cast<int>(src.getCols()), CV_8UC1, (void *)src.bitmap);
516  }
517 }
518 
519 void vpImageConvert::convert(const vpImage<float> &src, cv::Mat &dest, bool copyData)
520 {
521  if (copyData) {
522  cv::Mat tmpMap(static_cast<int>(src.getRows()), static_cast<int>(src.getCols()), CV_32FC1, (void *)src.bitmap);
523  dest = tmpMap.clone();
524  }
525  else {
526  dest = cv::Mat(static_cast<int>(src.getRows()), static_cast<int>(src.getCols()), CV_32FC1, (void *)src.bitmap);
527  }
528 }
529 
530 void vpImageConvert::convert(const vpImage<double> &src, cv::Mat &dest, bool copyData)
531 {
532  unsigned int nbRows = src.getRows();
533  unsigned int nbCols = src.getCols();
534  vpImage<float> I_float(nbRows, nbCols);
535  for (unsigned int i = 0; i < nbRows; ++i) {
536  for (unsigned int j = 0; j < nbCols; ++j) {
537  I_float[i][j] = static_cast<float>(src[i][j]);
538  }
539  }
540  convert(I_float, dest, copyData);
541 }
542 
543 void vpImageConvert::convert(const vpImage<vpRGBf> &src, cv::Mat &dest)
544 {
545  cv::Mat vpToMat(static_cast<int>(src.getRows()), static_cast<int>(src.getCols()), CV_32FC3, (void *)src.bitmap);
546  cv::cvtColor(vpToMat, dest, cv::COLOR_RGB2BGR);
547 }
548 
549 END_VISP_NAMESPACE
550 
551 #endif
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ badValue
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:73
@ fatalError
Fatal error.
Definition: vpException.h:72
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static void BGRaToGrey(unsigned char *bgra, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
unsigned int getWidth() const
Definition: vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:544
unsigned int getCols() const
Definition: vpImage.h:171
Type * bitmap
points toward the bitmap
Definition: vpImage.h:135
unsigned int getRows() const
Definition: vpImage.h:212
Definition: vpRGBa.h:70
unsigned char B
Blue component.
Definition: vpRGBa.h:180
unsigned char R
Red component.
Definition: vpRGBa.h:178
unsigned char G
Green component.
Definition: vpRGBa.h:179
@ alpha_default
Definition: vpRGBa.h:72
unsigned char A
Additionnal component.
Definition: vpRGBa.h:181
Definition: vpRGBf.h:64
float B
Blue component.
Definition: vpRGBf.h:151
float G
Green component.
Definition: vpRGBf.h:150
float R
Red component.
Definition: vpRGBf.h:149