图像滤镜
应用图像滤镜的不同方法。
背景
在使用 GDI 的大约 20 年里,我从来不需要做图像滤镜。"如果不是现在,那又是什么时候?"我决定从亮度和对比度开始。经过相对广泛的研究,我想出了三种合理的方法,并且既然我已经做了,我决定检查 GetPixel
/ SetPixel
的速度——它真的像大家说的那么慢吗?
目标
- 为了保持开放的心态和坚持 - 即使使用像 AForge 这样强大的工具,你通常也可以自己编写更好、更简单、更快的解决方案,而且只需相对较少的努力。
- 对于更高级的成员:在我看来 - 由于一些奇怪的原因,不安全模式非常流行。通常情况下,没有必要使用它 - 你可以通过简单的封送处理或其他方法来实现相同的目的。
- 最重要的是 – 将 QColorMatrix 从 C++ 翻译为 C#。在进行这项研究时 – 与使用 QColorMatrix 方法相比,我没有看到更好的图像过滤方法。这个主题非常高级;虽然代码本身非常简单且可读性很强,但数学相对复杂。除非我解释 ColorMatrix 的工作原理,否则我无法解释代码。但这**不是**本文的目标。如果您的数学水平足够高,并且您了解矩阵乘法和旋转,您可以很容易地理解和遵循代码。如果你的数学水平不够高,你可以像下面这样使用它 - 它有效 :)。
方法 1
首先,我的搜索把我带到了这篇文章:C# 中的图像处理实验室。它使用 AForge 库。我懒得寻找源代码。对我来说,使用 Refractory 并获取控制亮度和合同的对象要容易得多——这就是创建 AForgeFilter
对象的方式。关于 AForge 的方式,我有三点不喜欢的地方
- 不安全模式,您可能有业务需求不允许使用不安全模式。
- 在我看来:有时你可能想要同时应用亮度和对比度滤镜。使用 AForge,你不能这样做。
- 正如我的后续研究表明,它太慢了。
我非常容易地解决了第一个问题——只需使用封送处理而不是不安全模式。附件中的演示展示了处理图像需要多长时间。我无法注意到封送处理比不安全模式慢,那么为什么要使用不安全模式呢?
方法 2
不幸的是,我没有保留我找到第二种方法算法的链接。(OtherFilter
对象)。与 AForge 相比,它**简单得多**,而且速度更快。
方法 3
我并不完全满意。有一个 ColorMatrix
对象。一定有一种方法可以使用它进行图像过滤。我看到的下一篇文章是:玩转 ColorMatrix 作者:Sjaak Priester。幸运的是,我同样精通 C++ 和 C#。QColorMatrix
或多或少是原始 C++ QColorMatrix
的直接翻译。它有多快?应用四个滤镜和 Gamma 比第二种方法快 ~2 倍,比 AForge 快 ~7 倍……
方法 4
如果还有人没有被说服不要使用 GetPixel
/ SetPixel
方法 (OtherFilterSlow
对象) – 请看看它有多慢:~慢 10 倍。仍然想使用它吗?
使用代码
请注意:如果您要使用 AForgeFilter
对象,您需要与 AForge 社区核实。我不知道他们的许可证是什么,我的代码只是从 aforge.dll 重新构造的。否则,代码的使用方式如下所述。要调整亮度
Bitmap pSource = global::WindowsFormsApplication14.Properties.Resources.untitled;
AForgeFilter pFilterBrightness = new AForgeFilter();
pFilterBrightness.AdjustValue = (double)TrackBarBrightness1.Value / 1000;
Bitmap pBitmapBrightness = pFilterBrightness.Apply(pSource);
要调整对比度
Bitmap pSource = global::WindowsFormsApplication14.Properties.Resources.untitled;
AForgeFilter pFilterContrast= new AForgeFilter();
pFilterContrast.Factor = (double)TrackBarContrast1.Value / 1000;
Bitmap pBitmapBrightness = pFilterContrast.Apply(pSource);
在该示例中,我想比较安全模式和不安全模式,并同时更改亮度和对比度。这是代码
Bitmap pSource = global::WindowsFormsApplication14.Properties.Resources.untitled;
AForgeFilter pFilterBrightness = new AForgeFilter();
pFilterBrightness.AdjustValue = (double)TrackBarBrightness1.Value / 1000;
Bitmap pBitmapBrightness = checkBoxSafe.Checked ?
pFilterBrightness.ApplySafe(pSource) : pFilterBrightness.Apply(pSource);
AForgeFilter pFilterContrast = new AForgeFilter();
pFilterContrast.Factor = (double)TrackBarContrast1.Value / 1000;
Bitmap pBitmapContrast = checkBoxSafe.Checked ?
pFilterContrast.ApplySafe(pBitmapBrightness) :
pFilterContrast.Apply(pBitmapBrightness);
对于第二种方法
亮度
Bitmap pSource = global::WindowsFormsApplication14.Properties.Resources.untitled;
Bitmap pBitmap = pSource.Clone(new Rectangle(0, 0, pSource.Width, pSource.Height),
pSource.PixelFormat);
new Brightness().Adjust(pBitmap, TrackBarBrightness2.Value);
对比度
Bitmap pSource = global::WindowsFormsApplication14.Properties.Resources.untitled;
Bitmap pBitmap = pSource.Clone(new Rectangle(0, 0, pSource.Width, pSource.Height),
pSource.PixelFormat);
Contrast().Adjust(pBitmap, TrackBarContrast2.Value);
亮度和对比度
Bitmap pSource = global::WindowsFormsApplication14.Properties.Resources.untitled;
Bitmap pBitmap = pSource.Clone(new Rectangle(0, 0, pSource.Width, pSource.Height),
pSource.PixelFormat);
new BrightnessContrast().Adjust(pBitmap, TrackBarBrightness2.Value, TrackBarContrast2.Value);
第三种方法允许您更改四个滤镜和伽马
QColorMatrix pQColorMatrix = new QColorMatrix();
pQColorMatrix.ScaleColors(TrackBarContrast3.Value * 0.05f,
QColorMatrix.MatrixOrder.MatrixOrderPrepend);
pQColorMatrix.TranslateColors(TrackBarBrightness3.Value * 0.05f,
QColorMatrix.MatrixOrder.MatrixOrderAppend);
pQColorMatrix.SetSaturation(TrackBarSaturation3.Value * 0.05f,
QColorMatrix.MatrixOrder.MatrixOrderAppend);
pQColorMatrix.RotateHue(TrackBarHue3.Value * 4.0f);
Bitmap pSource = global::WindowsFormsApplication14.Properties.Resources.untitled;
Bitmap pResult = pQColorMatrix.Adjust(pSource, TrackBarGamma3.Value * 0.05f);