【问题标题】:Faster method of changing an image hue?改变图像色调的更快方法?
【发布时间】:2011-08-06 01:50:24
【问题描述】:

当我滑过轨迹栏时,是否有更好的方法可以平滑地更改图像的色调?我正在做的是获取每个像素的 RGB 值,计算饱和度和亮度,然后将值放入。图像的大小会影响色调更新的速度。 Photoshop 的图像色调功能将色调从 0 平滑地更改为 360,这是我想要尝试并达到的效果。

data = editImage.LockBits(new Rectangle(0, 0, editWidth, editHeight), 
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte* dataPtr = (byte*)data.Scan0;
h = trackBar1.Value / 60.0;
D = 1 - Math.Abs((h % 2) - 1);

if (h >= 0 && h < 1)
{
    for (int i = 0; i < editHeight; i++)
    {
        offsetStride = i * data.Stride;
        for (int j = 0; j < editWidth; j++)
        {
            blue = dataPtr[(j * 3) + offsetStride];
            green = dataPtr[(j * 3) + offsetStride + 1];
            red = dataPtr[(j * 3) + offsetStride + 2];

            if (green > blue) max = green;
            else max = blue;
            if (red > max) max = red;

            if (green < blue) min = green;
            else min = blue;
            if (red < min) min = red;

            s = (max == 0) ? 0 : 1d - (1d * min / max);
            v = max / 255d;

            C = v * s;
            X = C * D;
            E = v - C;

            dataPtr[(j * 3) + offsetStride] = (byte)(min);
            dataPtr[(j * 3) + offsetStride + 1] = (byte)((X + E) * 255);
            dataPtr[(j * 3) + offsetStride + 2] = (byte)(max);
        }
    }
}

【问题讨论】:

    标签: c# image-processing hue


    【解决方案1】:

    如果您想要改变色调的单色图像,那么最有效的方法是生成红色、黄色、绿色、青色、蓝色和洋红色图像,并根据需要在它们之间进行插值。

    因此,要生成 10% 旋转的图像,您需要添加 50/60 * red + 10/60 * yellow 并显示它。

    事实上,您并不需要生成所有 6 张图像。生成红色和黄色图像就足够了。您可以即时生成其他图像,因为例如,蓝色图像只是红色图像,但红色和蓝色像素交换了(您甚至可以从红色中导出黄色)。但最简单的方法可能是从 6 张图片开始,然后再添加优化。

    生成初始彩色图像的代码与上面的代码相似(乍一看),但从 HSV 到 RGB 的最后一步看起来有点可疑 - 维基百科页面很好地解释了这一点(而且它是可能的 C# 包含一个库函数来执行此转换)。

    [鉴于您的澄清,以下内容与您正在做的事情无关]

    如果您想逐个像素地改变色调(因此红色变为黄色,而绿色变为青色),那么您可以先将整个图像转换为 HSV,然后再进行处理,从而节省一些时间。

    您可以通过生成多个图像(例如色调每旋转 10 度)然后在它们之间进行插值来节省更多时间(在变换色调时)。但它比单色情况更复杂,因为某些像素(在插值期间色调移动通过 60 度的倍数的像素)需要特殊处理。因此,您还需要预先检测这些,然后即时计算它们。有一个权衡,因为您拥有的中间图像越多,特殊情况所需的像素就越少。在实践中,懒惰地(按需)生成单独的图像会加快启动速度,因为通常人们只做很小的改变。

    【讨论】:

    • 我想改变整个图像的色调。因此,如果我有一个 RGB 图像并将色调更改为 60,则图像看起来就像一个灰度图像,上面有一个黄色滤镜。
    • 我刚刚意识到我有一个错误并更新了上面的文字 - 你需要 6 张图片,而不是 3 张。
    【解决方案2】:

    您可以尝试使用查找表来摆脱对“s”的计算,因为 min 和 max 只能在 0 到 255 之间。所以你会有s = getS(min, max)。 C 和 E 的值可能也可以保存在这张表中(但已经很晚了,我还没有那么努力)。

    getS 表的每个元素都会像这样预先计算

    for (int min = 0; min < 255; min++)
    {
        for (int max = 0; max < 255; max++)
        {
            tableS[min, max] = (max == 0) ? 0 : 1d - (1d * min / max);
        }
    }
    

    Photoshop 的代码可能也是用汇编程序编写的,以获得最佳性能。

    为了看看这是否会有很大的效果,你可以注释掉所有的色调计算代码,看看它是如何通过复制假数据来执行的。如果它和 Photoshop 一样快,那么您知道这些计算是您的瓶颈。

    【讨论】:

    • 预先计算 s 和 v d 的值似乎确实使它更快一点。不过,我认为预先计算 C 是不可行的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-29
    • 2021-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 1970-01-01
    相关资源
    最近更新 更多