Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/15.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
C++ 如何将颜色表应用于灰度8位图像并在Qt中正确转换?_C++_Image_Qt_Image Processing - Fatal编程技术网

C++ 如何将颜色表应用于灰度8位图像并在Qt中正确转换?

C++ 如何将颜色表应用于灰度8位图像并在Qt中正确转换?,c++,image,qt,image-processing,C++,Image,Qt,Image Processing,我想把我的灰度图像转换成带颜色表的索引图像。我发现并测试了能够准确生成colormap()的函数——以下是我的代码: for (double i = 0; i < 256; ++i) { double hi = 255; double lo = 0; double r = -4.0 * std::abs(i - 255.0 * 3.0 / 4) + 255.0 * 3.0 / 2; double g = -4.0 * std::abs(i - 255.0

我想把我的灰度图像转换成带颜色表的索引图像。我发现并测试了能够准确生成colormap()的函数——以下是我的代码:

for (double i = 0; i < 256; ++i) {

    double hi = 255;
    double lo = 0;
    double r = -4.0 * std::abs(i - 255.0 * 3.0 / 4) + 255.0 * 3.0 / 2;
    double g = -4.0 * std::abs(i - 255.0 * 2.0 / 4) + 255.0 * 3.0 / 2;
    double b = -4.0 * std::abs(i - 255.0 * 1.0 / 4) + 255.0 * 3.0 / 2;


    CP->colortable.append(qRgb(r < lo ? lo : r > hi ? hi : r, g < lo ? lo : g > hi ? hi : g, b < lo ? lo : b > hi ? hi : b));


}
你可以看到这张图片中没有红色

尽管我知道青色部分的值是255像素。看起来是用蓝色代替了红色。这是一个简单的格式错误吗

以下是MATLAB jet颜色贴图的规格化外观

下面是我的图像应该是什么样子


.

首先,我检查了OP的颜色表曝光算法是否提供了合理的值。为此,我围绕上公开的代码编写了一个小样本,并用眼睛检查生成的值。输出看起来合理(根据MatLab提供的快照)——我认为这不是问题所在

接下来我调查了

q = QImage((uchar*)p->GetBuffer(), p->GetWidth(), p->GetHeight(), QImage::Format_Grayscale8);


QImage c = q.convertToFormat(QImage::Format_Indexed8, colortable);

ui->imageLabel->setPixmap(QPixmap::fromImage(c));
医生。所用功能的名称:

QImage QImage::convertToFormat(QImage::Format Format,常量QVector&colorTable,Qt::IMAGECONVERTIONFLAGS flags=Qt::AutoColor)常量 这是一个重载函数

使用指定的颜色表返回转换为给定格式的图像副本

从RGB格式到索引格式的转换是一个缓慢的操作,将使用直接的最近颜色方法,没有抖动

没有什么真正的帮助。最后一句直截了当的近似颜色让我有些怀疑

因此,我怀疑它是否只是将数据值作为索引重新使用到颜色表中。但这正是OP真正想要做的

事实上,我想要一些像“重新诠释演员”的形象

因此,我提出了这种方法:

  • 创建具有原始图像宽度和高度的
    QImage
    ,以及
    QImage::Format_Indexed8
  • 按照OP的建议设置此图像的颜色表
  • 将原始图像的数据复制到此图像中
  • 示例
    testQImageGrayToRGB.cc

    #include <vector>
    
    #include <QtWidgets>
    
    typedef unsigned char uchar;
    
    QImage buildSample(const int w = 256, const int h = 32)
    {
      QImage qImg(w, h, QImage::Format_Grayscale8);
      const int bpl = qImg.bytesPerLine();
      for (int y = 0; y < h; ++y) {
        uchar *row = qImg.bits() + y * bpl;
        for (int x = 0; x < w; ++x) {
          row[x] = (uchar)(x * 255 / (w - 1));
        }
      }
      return qImg;
    }
    
    const QVector<QRgb> makeColorTable()
    {
      QVector<QRgb> qColTbl;
      const double hi = 255;
      const double lo = 0;
      for (double i = 0; i < 256; ++i) {
        double r = -4.0 * std::abs(i - 255.0 * 3.0 / 4) + 255.0 * 3.0 / 2;
        double g = -4.0 * std::abs(i - 255.0 * 2.0 / 4) + 255.0 * 3.0 / 2;
        double b = -4.0 * std::abs(i - 255.0 * 1.0 / 4) + 255.0 * 3.0 / 2;
        qColTbl.append(
          qRgb(
            r < lo ? lo : r > hi ? hi : r,
            g < lo ? lo : g > hi ? hi : g,
            b < lo ? lo : b > hi ? hi : b));
      }
      return qColTbl;
    }
    
    QImage colorize(const QImage &qImg, const QVector<QRgb> &qColTbl)
    {
      const int w = qImg.width(), h = qImg.height();
      QImage qImgDst(w, h, QImage::Format_Indexed8);
      qImgDst.setColorTable(qColTbl);
      const int bpl = qImg.bytesPerLine();
      const int bplDst = qImgDst.bytesPerLine();
      for (int y = 0; y < h; ++y) {
        const uchar *row = qImg.bits() + y * bpl;
        uchar *rowDst = qImgDst.bits() + y * bplDst;
        std::copy(row, row + w, rowDst);
      }
      return qImgDst;
    }
    
    int main(int argc, char **argv)
    {
      qDebug() << "Qt Version:" << QT_VERSION_STR;
      QApplication app(argc, argv);
      // build contents
      const QImage qImgGray = buildSample();
      const QVector<QRgb> qColTbl = makeColorTable();
      const QImage qImgColorOP
        = qImgGray.convertToFormat(QImage::Format_Indexed8, qColTbl);
      const QImage qImgColorDS
        = colorize(qImgGray, qColTbl);
      // build some GUI
      QWidget win;
      QVBoxLayout qVBox;
      QLabel qLblGray(
        QString::fromUtf8("QImage Source: (QImage::Format_Grayscale8)"));
      qVBox.addWidget(&qLblGray);
      QLabel qLblImgGray;
      qLblImgGray.setPixmap(QPixmap::fromImage(qImgGray));
      qVBox.addWidget(&qLblImgGray);
      QLabel qLblColorOP(
        QString::fromUtf8("QImage Colorized: (Attempt of OP)"));
      qVBox.addWidget(&qLblColorOP);
      QLabel qLblImgColorOP;
      qLblImgColorOP.setPixmap(QPixmap::fromImage(qImgColorOP));
      qVBox.addWidget(&qLblImgColorOP);
      QLabel qLblColorDS(
        QString::fromUtf8("QImage Colorized: (Attempt of DS)"));
      qVBox.addWidget(&qLblColorDS);
      QLabel qLblImgColorDS;
      qLblImgColorDS.setPixmap(QPixmap::fromImage(qImgColorDS));
      qVBox.addWidget(&qLblImgColorDS);
      win.setLayout(&qVBox);
      win.show();
      // exec. application
      return app.exec();
    }
    
    输出(VisualStudio 2013,第5.9.2节):

    哎呀。中间的图像(应该类似于OP的方法)看起来与预期的OPs样本略有不同

    然而,通过我的“重新解释演员阵容”方法获得的底部图像看起来确实像预期的那样

    为了好玩,我在中再次构建了示例:

    $qmake-qt5 testQImageGrayToRGB.pro
    $make&./testQImageGrayToRGB
    g++-c-fno保持内联dllexport-D_GNU_SOURCE-pipe-O2-Wall-W-D_REENTRANT-DQT_NO_DEBUG-DQT_WIDGETS-LIB-DQT_GUI_-LIB-DQT_CORE_-LIB-I.-isystem/usr/include/qt5-isystem/usr/include/qt5/QtWidgets-isystem/usr/include/qt5/QtGui-isystem/usr/include/QtGui-isystem/usr/include/QtGui-isystem/usr/usr/QtCore/QtCore-I.-I.-I/qttestQImageGrayToRGB.cc
    g++-o testQImageGrayToRGB.exe testQImageGrayToRGB.o-lQt5Widgets-lQt5Gui-lQt5Core-lGL-lpthread
    Qt版本:5.9.4
    
    输出(cygwin64,g++(GCC)7.4.0,Qt5.9.4):

    啊哈现在,中间图像的颜色与OP描述的颜色相似


    注意:


    实际上,灰度和索引图像可以共享相同的数据。这将使逐行复制过时。但是,在这种情况下,必须仔细考虑拥有数据的
    QImage
    和共享数据的
    QImage
    的生命周期。

    首先,我检查OP的颜色表暴露算法是否提供了合理的值。为此,我围绕上公开的代码编写了一个小样本,并用眼睛检查生成的值。输出看起来合理(根据MatLab提供的快照)——我认为这不是问题所在

    接下来我调查了

    q = QImage((uchar*)p->GetBuffer(), p->GetWidth(), p->GetHeight(), QImage::Format_Grayscale8);
    
    
    QImage c = q.convertToFormat(QImage::Format_Indexed8, colortable);
    
    ui->imageLabel->setPixmap(QPixmap::fromImage(c));
    
    医生。所用功能的名称:

    QImage QImage::convertToFormat(QImage::Format Format,常量QVector&colorTable,Qt::IMAGECONVERTIONFLAGS flags=Qt::AutoColor)常量 这是一个重载函数

    使用指定的颜色表返回转换为给定格式的图像副本

    从RGB格式到索引格式的转换是一个缓慢的操作,将使用直接的最近颜色方法,没有抖动

    没有什么真正的帮助。最后一句直截了当的近似颜色让我有些怀疑

    因此,我怀疑它是否只是将数据值作为索引重新使用到颜色表中。但这正是OP真正想要做的

    事实上,我想要一些像“重新诠释演员”的形象

    因此,我提出了这种方法:

  • 创建具有原始图像宽度和高度的
    QImage
    ,以及
    QImage::Format_Indexed8
  • 按照OP的建议设置此图像的颜色表
  • 将原始图像的数据复制到此图像中
  • 示例
    testQImageGrayToRGB.cc

    #include <vector>
    
    #include <QtWidgets>
    
    typedef unsigned char uchar;
    
    QImage buildSample(const int w = 256, const int h = 32)
    {
      QImage qImg(w, h, QImage::Format_Grayscale8);
      const int bpl = qImg.bytesPerLine();
      for (int y = 0; y < h; ++y) {
        uchar *row = qImg.bits() + y * bpl;
        for (int x = 0; x < w; ++x) {
          row[x] = (uchar)(x * 255 / (w - 1));
        }
      }
      return qImg;
    }
    
    const QVector<QRgb> makeColorTable()
    {
      QVector<QRgb> qColTbl;
      const double hi = 255;
      const double lo = 0;
      for (double i = 0; i < 256; ++i) {
        double r = -4.0 * std::abs(i - 255.0 * 3.0 / 4) + 255.0 * 3.0 / 2;
        double g = -4.0 * std::abs(i - 255.0 * 2.0 / 4) + 255.0 * 3.0 / 2;
        double b = -4.0 * std::abs(i - 255.0 * 1.0 / 4) + 255.0 * 3.0 / 2;
        qColTbl.append(
          qRgb(
            r < lo ? lo : r > hi ? hi : r,
            g < lo ? lo : g > hi ? hi : g,
            b < lo ? lo : b > hi ? hi : b));
      }
      return qColTbl;
    }
    
    QImage colorize(const QImage &qImg, const QVector<QRgb> &qColTbl)
    {
      const int w = qImg.width(), h = qImg.height();
      QImage qImgDst(w, h, QImage::Format_Indexed8);
      qImgDst.setColorTable(qColTbl);
      const int bpl = qImg.bytesPerLine();
      const int bplDst = qImgDst.bytesPerLine();
      for (int y = 0; y < h; ++y) {
        const uchar *row = qImg.bits() + y * bpl;
        uchar *rowDst = qImgDst.bits() + y * bplDst;
        std::copy(row, row + w, rowDst);
      }
      return qImgDst;
    }
    
    int main(int argc, char **argv)
    {
      qDebug() << "Qt Version:" << QT_VERSION_STR;
      QApplication app(argc, argv);
      // build contents
      const QImage qImgGray = buildSample();
      const QVector<QRgb> qColTbl = makeColorTable();
      const QImage qImgColorOP
        = qImgGray.convertToFormat(QImage::Format_Indexed8, qColTbl);
      const QImage qImgColorDS
        = colorize(qImgGray, qColTbl);
      // build some GUI
      QWidget win;
      QVBoxLayout qVBox;
      QLabel qLblGray(
        QString::fromUtf8("QImage Source: (QImage::Format_Grayscale8)"));
      qVBox.addWidget(&qLblGray);
      QLabel qLblImgGray;
      qLblImgGray.setPixmap(QPixmap::fromImage(qImgGray));
      qVBox.addWidget(&qLblImgGray);
      QLabel qLblColorOP(
        QString::fromUtf8("QImage Colorized: (Attempt of OP)"));
      qVBox.addWidget(&qLblColorOP);
      QLabel qLblImgColorOP;
      qLblImgColorOP.setPixmap(QPixmap::fromImage(qImgColorOP));
      qVBox.addWidget(&qLblImgColorOP);
      QLabel qLblColorDS(
        QString::fromUtf8("QImage Colorized: (Attempt of DS)"));
      qVBox.addWidget(&qLblColorDS);
      QLabel qLblImgColorDS;
      qLblImgColorDS.setPixmap(QPixmap::fromImage(qImgColorDS));
      qVBox.addWidget(&qLblImgColorDS);
      win.setLayout(&qVBox);
      win.show();
      // exec. application
      return app.exec();
    }
    
    输出(VisualStudio 2013,第5.9.2节):

    哎呀。中间的图像(应该类似于OP的方法)看起来与预期的OPs样本略有不同

    然而,通过我的“重新解释演员阵容”方法获得的底部图像看起来确实像预期的那样

    为了好玩,我在中再次构建了示例:

    $qmake-qt5 testQImageGrayToRGB.pro
    $make&./testQImageGrayToRGB
    g++-c-fno保持内联dllexport-D_GNU_SOURCE-pipe-O2-Wall-W-D_REENTRANT-DQT_NO_DEBUG-DQT_WIDGETS-LIB-DQT_GUI_-LIB-DQT_CORE_-LIB-I.-isystem/usr/include/qt5-isystem/usr/include/qt5/QtWidgets-isystem/usr/include/qt5/QtGui-isystem/usr/include/QtGui-isystem/usr/include/QtGui-isystem/usr/usr/QtCore/QtCore-I.-I.-I/qttestQImageGrayToRGB.cc
    g++-o testQImageGrayToRGB.exe testQImageGrayToRGB.o-lQt5Widgets-lQt5Gui-lQt5Core-lGL-lpthread
    Qt版本:5.9.4
    
    输出(cygwin64,g++(GCC)7.4.0,Qt5.9.4):

    啊哈现在是