Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将OpenCV::Mat转换为QImage 我想知道我如何将OpenCV C++标准CV::Mat类型转换为QImage。我一直在四处寻找,但运气不好。我发现了一些将IPlimage转换为QImage的代码,但这不是我想要的。谢谢。_C++_Qt_Opencv_Qimage - Fatal编程技术网

如何将OpenCV::Mat转换为QImage 我想知道我如何将OpenCV C++标准CV::Mat类型转换为QImage。我一直在四处寻找,但运气不好。我发现了一些将IPlimage转换为QImage的代码,但这不是我想要的。谢谢。

如何将OpenCV::Mat转换为QImage 我想知道我如何将OpenCV C++标准CV::Mat类型转换为QImage。我一直在四处寻找,但运气不好。我发现了一些将IPlimage转换为QImage的代码,但这不是我想要的。谢谢。,c++,qt,opencv,qimage,C++,Qt,Opencv,Qimage,cv::Mat有一个到IplImage的转换操作符,因此如果您有一些东西可以将IplImage转换为QImage,只需使用它(或者进行-可能是轻微的-调整以直接获取cv::Mat,内存布局是相同的,“只是”标题不同。)要将cv::Mat转换为QImage,您可以尝试使用QImage(uchar*数据、int-width、int-height、Format-Format)构造函数,如下所示(Mat是cv::Mat): 它比手动将像素转换为QImage更有效,但您必须将原始cv::Mat图像保留在内

cv::Mat有一个到IplImage的转换操作符,因此如果您有一些东西可以将IplImage转换为QImage,只需使用它(或者进行-可能是轻微的-调整以直接获取cv::Mat,内存布局是相同的,“只是”标题不同。)

要将
cv::Mat
转换为
QImage
,您可以尝试使用
QImage(uchar*数据、int-width、int-height、Format-Format)
构造函数,如下所示(
Mat
cv::Mat
):

它比手动将像素转换为
QImage
更有效,但您必须将原始
cv::Mat
图像保留在内存中。它可以很容易地转换为
QPixmap
,并使用
QLabel
显示:

QPixmap pixmap = QPixmap::fromImage(img);
myLabel.setPixmap(pixmap);
更新

因为OpenCV默认使用BGR顺序,所以您应该首先使用
cvtColor(src、dst、CV_BGR2RGB)
来获得Qt理解的图像布局

更新2:

如果您试图显示的图像具有非标准(当它是非连续的子矩阵时),则图像可能会出现扭曲。在这种情况下,最好使用
cv::Mat::step1()
显式指定步幅:

演示如何将
QImage
转换为OpenCV的
IplImage
,反之亦然

之后,如果您需要帮助在
IplImage*
cv::Mat
之间转换:

// Assume data is stored by: 
// IplImage* image;

cv::Mat mat(image, true); // Copies the data from image

cv::Mat mat(image, false); // Doesn't copy the data!

这是一个黑客程序,但可以完成任务。

这里是24位RGB和灰度浮点的代码。可轻松调整其他类型。这是最有效的

QImage Mat2QImage(const cv::Mat3b &src) {
        QImage dest(src.cols, src.rows, QImage::Format_ARGB32);
        for (int y = 0; y < src.rows; ++y) {
                const cv::Vec3b *srcrow = src[y];
                QRgb *destrow = (QRgb*)dest.scanLine(y);
                for (int x = 0; x < src.cols; ++x) {
                        destrow[x] = qRgba(srcrow[x][2], srcrow[x][1], srcrow[x][0], 255);
                }
        }
        return dest;
}


QImage Mat2QImage(const cv::Mat_<double> &src)
{
        double scale = 255.0;
        QImage dest(src.cols, src.rows, QImage::Format_ARGB32);
        for (int y = 0; y < src.rows; ++y) {
                const double *srcrow = src[y];
                QRgb *destrow = (QRgb*)dest.scanLine(y);
                for (int x = 0; x < src.cols; ++x) {
                        unsigned int color = srcrow[x] * scale;
                        destrow[x] = qRgba(color, color, color, 255);
                }
        }
        return dest;
}
QImage Mat2QImage(常量cv::Mat3b和src){
QImage dest(src.cols、src.rows、QImage::Format_ARGB32);
对于(int y=0;y

这就是我的工作。我修改了上面Michal Kottman的代码。

Michal Kottman的答案是有效的,并给出了一些图像的预期结果,但在某些情况下会失败。这是我找到的解决这个问题的办法

QImage imgIn= QImage((uchar*) img.data, img.cols, img.rows, img.step, QImage::Format_RGB888);

不同之处在于增加了img.step部分。qt没有它不会抱怨,但是一些图像没有它就不能正常显示。希望这会有所帮助。

对深度图像使用静态函数convert16uc1:

QPixmap Viewer::convert16uc1(const cv::Mat& source)
{
  quint16* pSource = (quint16*) source.data;
  int pixelCounts = source.cols * source.rows;

  QImage dest(source.cols, source.rows, QImage::Format_RGB32);

  char* pDest = (char*) dest.bits();

  for (int i = 0; i < pixelCounts; i++)
  {
    quint8 value = (quint8) ((*(pSource)) >> 8);
    *(pDest++) = value;  // B
    *(pDest++) = value;  // G
    *(pDest++) = value;  // R
    *(pDest++) = 0;      // Alpha
    pSource++;
  }

  return QPixmap::fromImage(dest);
}

QPixmap Viewer::convert8uc3(const cv::Mat& source)
{
  quint8* pSource = source.data;
  int pixelCounts = source.cols * source.rows;

  QImage dest(source.cols, source.rows, QImage::Format_RGB32);

  char* pDest = (char*) dest.bits();

  for (int i = 0; i < pixelCounts; i++)
  {
    *(pDest++) = *(pSource+2);    // B
    *(pDest++) = *(pSource+1);    // G
    *(pDest++) = *(pSource+0);    // R
    *(pDest++) = 0;               // Alpha
    pSource+=3;
  }

  return QPixmap::fromImage(dest);
}

QPixmap Viewer::convert16uc3(const cv::Mat& source)
{
  quint16* pSource = (quint16*) source.data;
  int pixelCounts = source.cols * source.rows;

  QImage dest(source.cols, source.rows, QImage::Format_RGB32);

  char* pDest = (char*) dest.bits();

  for (int i = 0; i < pixelCounts; i++)
  {
    *(pDest++) = *(pSource+2);    // B
    *(pDest++) = *(pSource+1);    // G
    *(pDest++) = *(pSource+0);    // R
    *(pDest++) = 0;               // Alpha
    pSource+=3;
  }

  return QPixmap::fromImage(dest);
}
QPixmap查看器::convert16uc1(const-cv::Mat&source)
{
quint16*pSource=(quint16*)source.data;
int pixelCounts=source.cols*source.rows;
QImage dest(source.cols、source.rows、QImage::Format_RGB32);
char*pDest=(char*)dest.bits();
对于(int i=0;i>8);
*(pDest++)=值;//B
*(pDest++)=值;//G
*(pDest++)=值;//R
*(pDest++)=0;//α
pSource++;
}
返回QPixmap::fromImage(dest);
}
QPixmap查看器::convert8uc3(常量cv::Mat和源)
{
quint8*pSource=source.data;
int pixelCounts=source.cols*source.rows;
QImage dest(source.cols、source.rows、QImage::Format_RGB32);
char*pDest=(char*)dest.bits();
对于(int i=0;i
这对我很有帮助。它有点狡猾,性能很差(如评论中所指出的),但是可以使用到目前为止我所使用的所有颜色格式,而且操作非常简单

程序如下:

cv::Mat image = //...some image you want to display

// 1. Save the cv::Mat to some temporary file
cv::imwrite("../Images/tmp.jpg",image);

// 2. Load the image you just saved as a QImage
QImage img;
img.load("../Images/tmp.jpg");
完成

例如,如果要在QLabel中显示它,请继续执行以下操作:

// Set QImage as content of MyImageQLabel
ui-> MyImageQLabel->setPixmap(QPixmap::fromImage(img, Qt::AutoColor));

我个人将其用于一个简单的图像编辑器。

我也有与您相同的问题,因此我开发了四个函数来减轻我的痛苦,它们是

QImage mat_to_qimage_cpy(cv::Mat const &mat, bool swap = true);

QImage mat_to_qimage_ref(cv::Mat &mat, bool swap = true);

cv::Mat qimage_to_mat_cpy(QImage const &img, bool swap = true);

cv::Mat qimage_to_mat_ref(QImage &img, bool swap = true);
这些函数可以处理1、3、4个通道的图像,每个像素必须只占用一个字节(CV_8U->Format_Indexed8,CV_8UC3->QImage::Format_RGB888,CV_8UC4->QImage::Format_ARGB32),我还没有处理其他类型(QImage::Format_RGB16,QImage::Format_RGB666等等)。代码位于 在

**将mat转换为Qimage**的关键概念是

/**
 * @brief copy QImage into cv::Mat
 */
struct mat_to_qimage_cpy_policy
{
    static QImage start(cv::Mat const &mat, QImage::Format format)
    {
       //The fourth parameters--mat.step is crucial, because 
       //opencv may do padding on every row, you need to tell
       //the qimage how many bytes per row 
       //The last thing is if you want to copy the buffer of cv::Mat
       //to the qimage, you need to call copy(), else the qimage
       //will share the buffer of cv::Mat
       return QImage(mat.data, mat.cols, mat.rows, mat.step, format).copy();
    }
};

struct mat_to_qimage_ref_policy
{
    static QImage start(cv::Mat &mat, QImage::Format format)
    {
       //every thing are same as copy policy, but this one share
       //the buffer of cv::Mat but not copy
       return QImage(mat.data, mat.cols, mat.rows, mat.step, format);
    }
};
将cv::Mat转换为Qimage的关键概念是

/**
 * @brief copy QImage into cv::Mat
 */
struct qimage_to_mat_cpy_policy
{
    static cv::Mat start(QImage const &img, int format)
    {
       //same as convert mat to qimage, the fifth parameter bytesPerLine()
       //indicate how many bytes per row
       //If you want to copy the data you need to call clone(), else QImage
       //cv::Mat will share the buffer
       return cv::Mat(img.height(), img.width(), format, 
                      const_cast<uchar*>(img.bits()), img.bytesPerLine()).clone();
    }
};

/**
 * @brief make Qimage and cv::Mat share the same buffer, the resource
 * of the cv::Mat must not deleted before the QImage finish
 * the jobs.
 */
struct qimage_to_mat_ref_policy
{
    static cv::Mat start(QImage &img, int format)
    {
       //same as copy policy, but this one will share the buffer 
       return cv::Mat(img.height(), img.width(), format, 
                      img.bits(), img.bytesPerLine());
    }
};
/**
*@short将QImage复制到cv::Mat
*/
结构qimage_到材料cpy_策略
{
静态cv::Mat start(QImage const&img,int格式)
QImage mat_to_qimage_cpy(cv::Mat const &mat, bool swap = true);

QImage mat_to_qimage_ref(cv::Mat &mat, bool swap = true);

cv::Mat qimage_to_mat_cpy(QImage const &img, bool swap = true);

cv::Mat qimage_to_mat_ref(QImage &img, bool swap = true);
/**
 * @brief copy QImage into cv::Mat
 */
struct mat_to_qimage_cpy_policy
{
    static QImage start(cv::Mat const &mat, QImage::Format format)
    {
       //The fourth parameters--mat.step is crucial, because 
       //opencv may do padding on every row, you need to tell
       //the qimage how many bytes per row 
       //The last thing is if you want to copy the buffer of cv::Mat
       //to the qimage, you need to call copy(), else the qimage
       //will share the buffer of cv::Mat
       return QImage(mat.data, mat.cols, mat.rows, mat.step, format).copy();
    }
};

struct mat_to_qimage_ref_policy
{
    static QImage start(cv::Mat &mat, QImage::Format format)
    {
       //every thing are same as copy policy, but this one share
       //the buffer of cv::Mat but not copy
       return QImage(mat.data, mat.cols, mat.rows, mat.step, format);
    }
};
/**
 * @brief copy QImage into cv::Mat
 */
struct qimage_to_mat_cpy_policy
{
    static cv::Mat start(QImage const &img, int format)
    {
       //same as convert mat to qimage, the fifth parameter bytesPerLine()
       //indicate how many bytes per row
       //If you want to copy the data you need to call clone(), else QImage
       //cv::Mat will share the buffer
       return cv::Mat(img.height(), img.width(), format, 
                      const_cast<uchar*>(img.bits()), img.bytesPerLine()).clone();
    }
};

/**
 * @brief make Qimage and cv::Mat share the same buffer, the resource
 * of the cv::Mat must not deleted before the QImage finish
 * the jobs.
 */
struct qimage_to_mat_ref_policy
{
    static cv::Mat start(QImage &img, int format)
    {
       //same as copy policy, but this one will share the buffer 
       return cv::Mat(img.height(), img.width(), format, 
                      img.bits(), img.bytesPerLine());
    }
};
Mat mat = imread("path/to/image.jpg");
cvtColor(mat, mat, CV_BGR2RGB);
QImage image(mat.data, mat.cols, mat.rows, QImage::Format_RGB888);
QImage image = QImage(mat.data, mat.cols, mat.rows, QImage::Format_RGB888).rgbSwapped());