在图像处理领域,调整图像的亮度和对比度是常见的需求之一。本文将探讨几种在C#中实现这一功能的方法,并对比它们的性能。
在开始图像处理之前,从未考虑过使用图像滤镜。然而,随着项目需求的增加,意识到这是一个必须掌握的技能。决定从调整亮度和对比度开始,这是一个相对基础但非常重要的图像处理步骤。
目标是保持开放的心态和坚持不懈的态度。即使有像AForge这样强大的工具,往往可以通过少量的努力,编写出更好、更简单、更快的解决方案。
对于更高级的成员来说,注意到“不安全模式”非常受欢迎,但很多时候其实没有必要使用它——可以通过简单的封送处理或其他方式来实现相同的效果。
最重要的目标是将C++中的QColorMatrix翻译成C#。在进行这项研究时,没有发现比使用QColorMatrix更好的图像过滤方法。这个主题非常高级;虽然代码本身非常简单且易于阅读,但数学部分相对复杂。除非解释ColorMatrix的工作原理,否则无法解释代码。但这并非本文的目标。如果数学水平足够高,并且理解矩阵乘法和旋转,可以很容易地理解并跟随代码。如果数学水平不够,可以直接按照下面的例子使用它——它是有效的。
初步搜索带找到了这篇文章:。它使用了AForge库。懒得去找源代码。使用Refractory获取控制亮度和对比度的对象要容易得多——这就是如何创建AForgeFilter对象的。
不喜欢AForge方法的三件事:
很容易解决了第一个问题——只需使用封送处理代替不安全模式。附带的演示显示了处理图像需要多长时间。无法注意到封送处理比不安全模式慢,那么为什么要使用不安全模式呢?
不幸的是,没有保留发现第二种方法算法的链接。(OtherFilter对象)。它比AForge简单得多,而且速度更快。
并不完全满意。有一个ColorMatrix对象。必须有一种方法可以使用它进行图像过滤。接下来看到的这篇文章是:。幸运的是,同样精通C++和C#。
QColorMatrix几乎是原始C++ QColorMatrix的直接翻译。它有多快?应用四个滤镜和Gamma大约比第二种方法快2倍,比AForge快7倍……
如果有人还没有被说服不要使用GetPixel/SetColor方法(OtherFilterSlow对象)——看看它有多慢:大约慢10倍。还想使用它吗?
请注意:如果要使用AForgeFilter对象,需要检查AForge社区。不知道他们的许可证是什么,代码只是从aforge.dll的反射。否则,代码的使用如下所述。
C# Bitmap pSource = global::WindowsFormsApplication14.Properties.Resources.untitled;
AForgeFilter pFilterBrightness = new AForgeFilter();
pFilterBrightness.AdjustValue = (double)TrackBarBrightness1.Value / 1000;
Bitmap pBitmapBrightness = pFilterBrightness.Apply(pSource);
C# Bitmap pSource = global::WindowsFormsApplication14.Properties.Resources.untitled;
AForgeFilter pFilterContrast = new AForgeFilter();
pFilterContrast.Factor = (double)TrackBarContrast1.Value / 1000;
Bitmap pBitmapBrightness = pFilterContrast.Apply(pSource);
C# 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);
C# 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);
C# 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);
C# 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);
C# 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);