VAT  3.0
Video Analysis Tool
asmOpenCV.h
1 #ifndef __ASM_OPENCV_H__
2 #define __ASM_OPENCV_H__
3 
4 /*
5 Functions to convert between OpenCV's cv::Mat and Qt's QImage and QPixmap.
6 
7 Andy Maloney
8 23 November 2013
9 http://asmaloney.com/2013/11/code/converting-between-cvmat-and-qimage-or-qpixmap
10 */
11 
12 #include <QImage>
13 #include <QPixmap>
14 #include <QDebug>
15 
16 #include "opencv2/imgproc/imgproc.hpp"
17 #include "opencv2/imgproc/types_c.h"
18 
19 
20 namespace ASM {
21 inline QImage cvMatToQImage( const cv::Mat &inMat )
22 {
23  switch ( inMat.type() )
24  {
25  // 8-bit, 4 channel
26  case CV_8UC4:
27  {
28  QImage image( inMat.data, inMat.cols, inMat.rows, inMat.step, QImage::Format_RGB32 );
29 
30  return image;
31  }
32 
33  // 8-bit, 3 channel
34  case CV_8UC3:
35  {
36  QImage image( inMat.data, inMat.cols, inMat.rows, inMat.step, QImage::Format_RGB888 );
37 
38  return image.rgbSwapped();
39  }
40 
41  // 8-bit, 1 channel
42  case CV_8UC1:
43  {
44  static QVector<QRgb> sColorTable;
45 
46  // only create our color table once
47  if ( sColorTable.isEmpty() )
48  {
49  for ( int i = 0; i < 256; ++i )
50  sColorTable.push_back( qRgb( i, i, i ) );
51  }
52 
53  QImage image( inMat.data, inMat.cols, inMat.rows, inMat.step, QImage::Format_Indexed8 );
54 
55  image.setColorTable( sColorTable );
56 
57  return image;
58  }
59 
60  default:
61  qWarning() << "ASM::cvMatToQImage() - cv::Mat image type not handled in switch:" << inMat.type();
62  break;
63  }
64 
65  return QImage();
66 }
67 
68 inline QPixmap cvMatToQPixmap( const cv::Mat &inMat )
69 {
70  return QPixmap::fromImage( cvMatToQImage( inMat ) );
71 }
72 
73 // If inImage exists for the lifetime of the resulting cv::Mat, pass false to inCloneImageData to share inImage's
74 // data with the cv::Mat directly
75 // NOTE: Format_RGB888 is an exception since we need to use a local QImage and thus must clone the data regardless
76 inline cv::Mat QImageToCvMat( const QImage &inImage, bool inCloneImageData = true )
77 {
78  switch ( inImage.format() )
79  {
80  // 8-bit, 4 channel
81  case QImage::Format_RGB32:
82  {
83  cv::Mat mat( inImage.height(), inImage.width(), CV_8UC4, const_cast<uchar*>(inImage.bits()), inImage.bytesPerLine() );
84 
85  return (inCloneImageData ? mat.clone() : mat);
86  }
87 
88  // 8-bit, 3 channel
89  case QImage::Format_RGB888:
90  {
91  if ( !inCloneImageData )
92  qWarning() << "ASM::QImageToCvMat() - Conversion requires cloning since we use a temporary QImage";
93 
94  QImage swapped = inImage.rgbSwapped();
95 
96  return cv::Mat( swapped.height(), swapped.width(), CV_8UC3,
97  const_cast<uchar*>(swapped.bits()),
98  swapped.bytesPerLine() ).clone();
99  }
100 
101  // 8-bit, 1 channel
102  case QImage::Format_Indexed8:
103  {
104  cv::Mat mat( inImage.height(), inImage.width(), CV_8UC1, const_cast<uchar*>(inImage.bits()), inImage.bytesPerLine() );
105 
106  return (inCloneImageData ? mat.clone() : mat);
107  }
108 
109  default:
110  qWarning() << "ASM::QImageToCvMat() - QImage format not handled in switch:" << inImage.format();
111  break;
112  }
113 
114  return cv::Mat();
115 }
116 
117 // If inPixmap exists for the lifetime of the resulting cv::Mat, pass false to inCloneImageData to share inPixmap's data
118 // with the cv::Mat directly
119 // NOTE: Format_RGB888 is an exception since we need to use a local QImage and thus must clone the data regardless
120 inline cv::Mat QPixmapToCvMat( const QPixmap &inPixmap, bool inCloneImageData = true )
121 {
122  return QImageToCvMat( inPixmap.toImage(), inCloneImageData );
123 }
124 }
125 
126 #endif // __ASM_OPENCV_H__
Definition: asmOpenCV.h:20