3

我目前正在使用 QPainter 和 QImage 生成“热图”。我的方法包括用黑色到透明的 QRadialGradients 绘制多个圆圈作为 QBrush(参见“强度图”)。然后我将梯度图应用于强度图以获得所需的“热图”效果(参见“梯度图之后”)。

我遇到的问题(在“渐变图之后”图像中更为明显)是圆圈没有正确混合。圆圈重叠的地方似乎部分混合,但在边缘你可以清楚地看到圆圈结束的地方(几乎是外发光)。我想要一个在圆圈之间没有可见边界并且正确混合的效果。

强度图

强度图

梯度图后(不同强度图)

渐变映射后

代码

// Setup QImage and QPainter
QImage *map = new QImage(500, 500, QImage::Format_ARGB32);
map->fill(QColor(255, 255, 255, 255));
QPainter paint(map);
paint.setRenderHint(QPainter::HighQualityAntialiasing);

// Create Intensity map
std::vector<int> record = disp_data[idx]; // Data
for(int j = 1, c = record.size(); j < c; ++j) {
    int dm = 150 + record[j] * 100 / 255; // Vary the diameter

    QPen g_pen(QColor(0, 0, 0, 0));
    g_pen.setWidth(0);
    QRadialGradient grad(sensors[j-1].x, sensors[j-1].y, dm/2); // Create Gradient
    grad.setColorAt(0, QColor(0, 0, 0, record[j])); // Black, varying alpha
    grad.setColorAt(1, QColor(0, 0, 0, 0)); // Black, completely transparent
    QBrush g_brush(grad); // Gradient QBrush
    paint.setPen(g_pen);
    paint.setBrush(g_brush);
    paint.drawEllipse(sensors[j-1].x-dm/2, sensors[j-1].y-dm/2, dm, dm); // Draw circle
}

// Convert to heat map
for(int i = 0; i < 500; ++i) {
    for(int j = 0; j < 500; ++j) {
        int b = qGray(map->pixel(i, j));
        map->setPixel(i, j, grad_map->pixel(b, 0)); //grad_map is a QImage gradient map
    }
}

如您所见,圆圈没有 QPen。我一直在尝试各种混合模式,但没有成功。我还将渲染提示更改为 HighQualityAntialiasing。我也尝试过使圆比径向渐变大得多,因此无法将渐变截断或将边框应用于圆的外部。

有任何想法吗?谢谢!

4

2 回答 2

5

我认为这是马赫条纹的一种形式,这是一种视觉错觉,视觉系统会增强亮度的变化,从而导致图像中实际不存在的亮带或暗带的出现。通常这些可以在两个不同区域之间的边界上看到,但在这里的情况下,我相信这是观察到的梯度的明显不连续性。

这里有一些图片来演示这个问题:

第一个图像是在软件中计算的,由三个圆圈组成,每个圆圈都用径向线性渐变绘制。马赫带效应应该在圆之间重叠的边缘可见,因为这些是梯度急剧变化的点。

灰度,带状

第二张图像是完全相同的计算,但不是沿半径呈线性,而是将梯度映射到曲线(我使用了第一个 Hermite 基函数)。乐队应该几乎完全消失了:

灰度,平滑

至于为什么这会更多地影响彩色图像,我不确定它是否会这样做。我认为在上述情况下,可能由于着色实际上是调色板查找而导致了额外的条带,从而导致了额外的条带。

我在本地进行了大致相同的着色,也简单地映射了一个调色板,效果相似:

在此处输入图像描述 在此处输入图像描述

使用 QT 的线性渐变解决这个问题可能并不简单(您可以尝试向渐变添加更多控制点,但您必须添加很多...),但在软件中计算这样的图像并不难. 您还可以考虑其他一些后处理效果,例如添加模糊和/或添加噪点。任何打破梯度不连续性的东西都可能会有所帮助。

于 2012-12-22T13:08:25.923 回答
0

我同意 JasonD 的观点。

此外,请记住 Qt 在 sRGB 颜色空间中进行线性混合,它不是线性的(它应用了 gamma 2.2)。

要做到这一点,您需要在线性光中进行混合或插值,然后转换为 sRGB(应用伽玛)进行显示。

于 2012-12-22T16:03:03.970 回答