在 C# 中使用 ImageAttributes 旋转色调
如何使用 GDI+ 的 ImageAttributes(大概还有 ColorMatrix)旋转图像的色调?
请注意,我想旋转色调,而不是对图像进行着色。
编辑:通过旋转色调,我的意思是图像中的每种颜色应该转换为不同的颜色,而不是使整个图像变成一种颜色的阴影。
例如,
原始:http://www.codeguru.com/img/legacy /gdi/Tinter03.jpg
旋转:http://www. codeguru.com/img/legacy/gdi/Tinter15.jpg 或 http://www.codeguru.com/img/legacy/gdi/Tinter17.jpg
How can I rotate the hue of an image using GDI+'s ImageAttributes
(and presumably ColorMatrix
)?
Note that I want to rotate the hue, not tint the image.
EDIT: By rotating the hue, I mean that each color in the image should be shifted to a different color, as opposed to making the entire image a shade of one color.
For example,
Original:http://www.codeguru.com/img/legacy/gdi/Tinter03.jpg
Rotated: http://www.codeguru.com/img/legacy/gdi/Tinter15.jpg or http://www.codeguru.com/img/legacy/gdi/Tinter17.jpg
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我最终将 QColorMatrix 移植到 C# 并使用其
RotateHue
方法。I ended up porting QColorMatrix to C# and using its
RotateHue
method.图像处理的矩阵运算
Paul Haeberli
1993 年 11 月
简介
四乘四矩阵通常用于变换几何图形以进行 3D 渲染。 这些矩阵还可用于转换 RGB 颜色、缩放 RGB 颜色以及控制色调、饱和度和对比度。 使用矩阵最重要的优点是可以使用标准矩阵乘法组合任意数量的颜色变换。
请注意,为了使这些操作正确,我们确实必须对线性亮度值进行操作。 如果输入图像位于非线性亮度空间中,则在使用这些矩阵运算之前,必须将 RGB 颜色转换为线性空间。
颜色变换
RGB 颜色通过 4 x 4 矩阵进行变换,如下所示:
单位
这是单位矩阵:
通过单位矩阵变换颜色将使它们保持不变。
更改亮度
要缩放 RGB 颜色,请使用如下矩阵:
其中,
rscale
、gscale
和bscale
指定缩放 r、g 的程度和 b 颜色分量。 这可用于改变图像的色彩平衡。实际上,计算结果为:
转换为亮度
要将彩色图像转换为黑白图像,需要使用以下矩阵:
其中
这是亮度向量。 请注意,此处我们不使用标准 NTSC 权重 0.299、0.587 和 0.114。 NTSC 权重仅适用于 gamma 2.2 色彩空间中的 RGB 颜色。 对于线性 RGB 颜色,上述值更好。
实际上,这会计算:
修改饱和度
要使 RGB 颜色饱和,请使用此矩阵:
其中常数源自饱和度值
s
,如下所示:此饱和度矩阵的一个很好的属性是亮度保留输入 RGB 颜色。 该矩阵还可用于通过指定饱和度值 -1.0 来补充图像中的颜色。
请注意,当 s 设置为 0.0 时,该矩阵正是上述“转换为亮度”矩阵。 当 s 设置为 1.0 时,矩阵变为恒等式。 所有饱和矩阵都可以通过在这两个矩阵之间进行内插或外推来导出。
通过插值和外插进行图像处理。
将偏移应用于颜色分量
要偏移图像中颜色的 r、g 和 b 分量,请使用此矩阵:
这可以与颜色缩放一起使用来更改RGB 图像的对比度。
简单色调旋转
为了旋转色调,我们围绕对角向量 [1.0 1.0 1.0] 执行 RGB 颜色的 3D 旋转。 变换矩阵的推导如下所示:
如果我们有函数:
identmat(mat)
:创建一个单位矩阵。xrotatemat(mat,rsin,rcos)
:将绕 x(红色)轴旋转的矩阵相乘。zrotatemat(mat,rsin,rcos)
:将绕 z(蓝色)轴旋转的矩阵相乘。然后可以像这样构造一个绕 1.0,1.0,1.0 对角线旋转的矩阵:
首先,我们制作一个单位矩阵
将灰度向量旋转为正 Z
旋转色调
将灰度向量旋转回原位
得到的矩阵将旋转 的色调输入 RGB 颜色。 旋转 120.0 度将准确地将红色映射为绿色,将绿色映射为蓝色,将蓝色映射为红色。 然而,这种转换有一个问题,即输入颜色的亮度没有保留。 这可以通过以下改进来解决:
保持亮度的同时进行色相旋转
我们制作一个单位矩阵
identmat(mmat);
将灰色矢量旋转为正 Z
剪切空间以使亮度平面水平
旋转色调
取消剪切空间以将亮度平面放回
原位 将灰色矢量旋转回原位
结论
我已经介绍了可应用于 RGB 颜色的几种矩阵变换。 每个颜色变换都由 4 x 4 矩阵表示,类似于常用于变换 3D 几何形状的矩阵。
这些转换使我们能够单独调整图像对比度、亮度、色调和饱和度。 此外,颜色矩阵变换以类似于几何变换的方式连接。 任何操作序列都可以使用矩阵乘法组合成单个矩阵。
Matrix Operations for Image Processing
Paul Haeberli
Nov 1993
Introduction
Four by four matrices are commonly used to transform geometry for 3D rendering. These matrices may also be used to transform RGB colors, to scale RGB colors, and to control hue, saturation and contrast. The most important advantage of using matrices is that any number of color transformations can be composed using standard matrix multiplication.
Please note that for these operations to be correct, we really must operate on linear brightness values. If the input image is in a non-linear brightness space RGB colors must be transformed into a linear space before these matrix operations are used.
Color Transformation
RGB colors are transformed by a four by four matrix as shown here:
The Identity
This is the identity matrix:
Transforming colors by the identity matrix will leave them unchanged.
Changing Brightness
To scale RGB colors a matrix like this is used:
Where
rscale
,gscale
, andbscale
specify how much to scale the r, g, and b components of colors. This can be used to alter the color balance of an image.In effect, this calculates:
Converting to Luminance
To convert a color image into a black and white image, this matrix is used:
Where
This is the luminance vector. Notice here that we do not use the standard NTSC weights of 0.299, 0.587, and 0.114. The NTSC weights are only applicable to RGB colors in a gamma 2.2 color space. For linear RGB colors the values above are better.
In effect, this calculates:
Modifying Saturation
To saturate RGB colors, this matrix is used:
Where the constants are derived from the saturation value
s
as shown below:One nice property of this saturation matrix is that the luminance of input RGB colors is maintained. This matrix can also be used to complement the colors in an image by specifying a saturation value of -1.0.
Notice that when s is set to 0.0, the matrix is exactly the "convert to luminance" matrix described above. When s is set to 1.0 the matrix becomes the identity. All saturation matrices can be derived by interpolating between or extrapolating beyond these two matrices.
This is discussed in more detail in the note on Image Processing By Interpolation and Extrapolation.
Applying Offsets to Color Components
To offset the r, g, and b components of colors in an image this matrix is used:
This can be used along with color scaling to alter the contrast of RGB images.
Simple Hue Rotation
To rotate the hue, we perform a 3D rotation of RGB colors about the diagonal vector [1.0 1.0 1.0]. The transformation matrix is derived as shown here:
If we have functions:
identmat(mat)
: that creates an identity matrix.xrotatemat(mat,rsin,rcos)
: that multiplies a matrix that rotates about the x (red) axis.yrotatemat(mat,rsin,rcos)
: that multiplies a matrix that rotates about the y (green) axis.zrotatemat(mat,rsin,rcos)
: that multiplies a matrix that rotates about the z (blue) axis.Then a matrix that rotates about the 1.0,1.0,1.0 diagonal can be constructed like this:
First we make an identity matrix
Rotate the grey vector into positive Z
Rotate the hue
Rotate the grey vector back into place
The resulting matrix will rotate the hue of the input RGB colors. A rotation of 120.0 degrees will exactly map Red into Green, Green into Blue and Blue into Red. This transformation has one problem, however, the luminance of the input colors is not preserved. This can be fixed with the following refinement:
Hue Rotation While Preserving Luminance
We make an identity matrix
identmat(mmat);
Rotate the grey vector into positive Z
Shear the space to make the luminance plane horizontal
Rotate the hue
Unshear the space to put the luminance plane back
Rotate the grey vector back into place
Conclusion
I've presented several matrix transformations that may be applied to RGB colors. Each color transformation is represented by a 4 by 4 matrix, similar to matrices commonly used to transform 3D geometry.
These transformations allow us to adjust image contrast, brightness, hue and saturation individually. In addition, color matrix transformations concatenate in a way similar to geometric transformations. Any sequence of operations can be combined into a single matrix using matrix multiplication.
您看过 CodeProject 上的这篇文章吗?
诚然,快速浏览一下该页面,它看起来就像 4D 数学。 您可以采用与 2D 或 3D 数学类似的方法来构造矩阵。
采用一系列源“点”(在本例中您需要 4 个)和相应的目标“点”并生成一个矩阵。 然后可以将其应用于任何“点”。
要在 2D 中执行此操作(凭记忆,这样我就可以在此完成完整的咆哮):
源点是 (1, 0) 和 (0, 1)。 目标是 (0, -1) 和 (1,0)。 您需要的矩阵是:
其中额外信息是坐标的“w”值。
将其扩展到 {R, G, B, A, w},您将得到一个矩阵。 取 4 种颜色:红色 (1, 0, 0, 0, w)、绿色 (0, 1, 0, 0, w)、蓝色 (0, 0, 1, 0, w) 和透明 (0, 0, 0, 1、w)。 计算出它们在新方案中映射到什么颜色,并按如下方式构建矩阵:
注意:乘法的顺序(向量 * 矩阵或矩阵 * 向量)将确定变换后的点是垂直还是水平进入该矩阵,因为矩阵乘法是不可交换的。 我假设向量*矩阵。
Have you seen this article on CodeProject?
From an admittedly quick look at the page it looks like 4D maths. You can adopt a similar approach to contstructing matrices as you would for 2D or 3D maths.
Take a series of source "points" - in this case you'll need 4 - and the corresponding target "points" and generate a matrix. This can then be applied to any "point".
To do this in 2D (from memory so I could have made a complete howler in this):
Source points are (1, 0) and (0, 1). The targets are (0, -1) and (1,0). The matrix you need is:
Where the extra information is for the "w" value of the coordinate.
Extend this up to {R, G, B, A, w} and you'll have a matrix. Take 4 colours Red (1, 0, 0, 0, w), Green (0, 1, 0, 0, w), Blue (0, 0, 1, 0, w) and Transparent (0, 0, 0, 1, w). Work out what colours they map to in the new scheme and build up your matrix as follows:
NOTE: The order you do you mulitplication (vector * matrix or matrix * vector) will determine whether the transformed points go vertically or horizontally into this matrix, as matrix multiplication is non-commutative. I'm assuming vector * matrix.
这是一个老问题,但发布的解决方案比我找到的简单答案复杂得多。
简单:
重申问题:我们需要什么?
我准备了红色的图标。 有些区域是透明的,有些区域或多或少饱和,但它们都具有红色色调。 我认为它非常适合您的用例。 图像可能有其他颜色,它们只会被旋转。
如何表示要应用的色调? 最简单的答案是:提供
Color
。致力于解决方案
ColorMatrix
表示线性变换。显然,当颜色为红色时,变换应该是恒等的。
当颜色为绿色时,转换应将红色映射到绿色,将绿色映射到蓝色,将蓝色映射到红色。
执行此操作的 ColorMatrix 是:
数学解决方案
“啊哈”技巧是认识到矩阵的实际形式是
其中 R、G 和 B 只是着色颜色的分量!
示例代码
我在 https://code.msdn.microsoft.com/ 上获取了示例代码ColorMatrix-Image-Filters-f6ed20ae 。
我调整了它并在我的项目中实际使用它:
希望这会有所帮助。
限制
This is an old question but solutions posted are much more complicated than the simple answer I found.
Simple:
Restating the problem: what do we need ?
I prepared icons tinted red. Some areas are transparent, some are more or less saturated, but they all have red hue. I think it matches your use case very well. The images may have other colors, they will just be rotated.
How to represent the tint to apply ? The simplest answer is: supply a
Color
.Working towards a solution
ColorMatrix
represent a linear transformation.Obviously when Color is red, the transformation should be identity.
When color is green, the transformation should map red to green, green to blue, blue to red.
A ColorMatrix that does this is :
Mathematical solution
The "Aha" trick is to recognize that the actual form of the matrix is
where R, G and B are simply the component of the tinting color!
Sample code
I took example code on https://code.msdn.microsoft.com/ColorMatrix-Image-Filters-f6ed20ae .
I adjusted it and actually use this in my project:
Hope this helps.
Limitation
以下代码构造一个
ColorMatrix
来应用色调偏移。我的见解是,在色调空间 60° 偏移时:
实际上是 RGB 空间中的 45° 偏移:
因此您可以转动 120° 偏移的一部分变成 90° 偏移的一部分。
HueShift
参数必须是-1..1
之间的值。例如,为了应用 60° 偏移:
您可以调用:
实现:
The following code constructs a
ColorMatrix
for applying a hue shift.The insight i had was that at 60° shift in hue space:
is actually a 45° shift in RGB space:
So you can turn some fraction of a 120° shift into some fraction of a 90° shift.
The
HueShift
parameter must be a value between-1..1
.For example, in order to apply a 60° shift:
you call:
Implementation:
我构建了一个用 C# 语言实现 @IanBoid 代码的方法。
I build a method that implement @IanBoid code in c# language.
我想 www.aforgenet.com 可以提供帮助
I suppose that www.aforgenet.com could help
我将其放在一起来解决这个问题(帖子底部链接了 C# 项目的 ZIP 文件)。 它不使用
ImageAttributes
或ColorMatrix
,但它会按照您的描述旋转色调:I threw this together for this question (ZIP file with c# project linked at the bottom of the post). It does not use
ImageAttributes
orColorMatrix
, but it rotates the hue as you've described: