C++ 如何将颜色表应用于灰度8位图像并在Qt中正确转换?
我想把我的灰度图像转换成带颜色表的索引图像。我发现并测试了能够准确生成colormap()的函数——以下是我的代码: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
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
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
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):
啊哈现在是