基于C#的颜色空间转换
当前用于数字图像处理编程的主要是C++(例如Visual C++),原因是其具有灵活性,并运行能力快速高效。但另一方面也给开发带来了难度和降低了效率。C#是微软开发的一种面向对象的新型编程语言,是从C/C++中派生而来,保留了C/C++强大功能和灵活性,同时又具有Visual Basic的简单语法结构和高效开发能力。对于重点关注算法的数字图像处理研究,C#比较适合用来实现、验证和开发某种算法。本文介绍了基于C#的图像处理基本方法,并介绍了在彩色图像处理中常用的颜色空间及其转换的C#实现。
1 彩色图像处理颜色空间
颜色空间是彩色图像处理的基础,颜色空间的选取直接影响处理的方法和效果。在彩色图像处理中最常用的颜色空间包括RGB颜色空间和HSI(HSV) 颜色空间。前者常用于计算机输入输出设备(包括扫描仪和数码相机等)中,后者则更符合人类描述和解释颜色的方式。
在RGB颜色空间中,每种颜色出现在红(Red)、绿(Green)、蓝(Blue)的原色光谱分量中,其模型基于笛卡儿坐标系统。在此颜色空间,所表示的图像由三个图像分量(RGB)组成。
HSI颜色空间通过色度(Hue)、饱和度(Saturation)和亮度(Intensity)来表示物体的颜色。色度H定义了颜色的波长,反映了颜色最接近哪种光谱波长,既光的不同颜色。饱和度S表示颜色的深浅程度,S越高,颜色越深。I表示强度或亮度,I与颜色信息无关,而H和S包含了颜色信息。
由于HSI颜色空间中I分量与颜色信息无关,而H和S分量与人眼获得颜色的方式密切相关,因此比较适合于彩色图像处理。彩色数字图像的存储和显示一般采用RGB形式,所以常常需要进行RGB颜色空间和HSI颜色空间的相互转换。关于RGB和HSI的相互转换公式有不同的形式,但基本思想是相同的。从彩色图像处理的角度,只要色度是一个角度,饱和度和亮度独立,转换是可逆的,不会影响处理的结果。这里省略了这些公式的描述。
2 C#图像处理的基本方法
C#处理图像有三种方法:像素法、内存法和指针法。像素法应用GDI+中的方法,易于理解,方法简单,但运行速度慢;内存法把图像复制到内存中,直接对内存中的数据进行处理,运行速度比像素法快得多,程序难度也不大;指针法直接利用指针来对图像进行处理,速度最快。但C#建议不使用指针,因为使用指针,代码不仅难以编写和调试,而且无法利用CRL的内存类型安全检查,不能发挥C#的特长。下面介绍用内存法对图像处理的基本方法。
首先在处理图像的窗体类中定义一个字符串(图像文件名)和一个Bitmap类型的数据成员(图像对象),然后可以利用OpenFileDialog选择图像文件并读取文件名,再使用Image.FromFile创建图形对象。比如:
在窗体类中定义字符串(图像文件名)和Bitmap类型的数据成员(图像对象):
private string curFileName;
private System.Drawing.Bitmap curBitmap;
使用Image.FromFile创建图形对象:
curBitmap = (Bitmap)Image.FromFile(curFileName);
把图像复制到内存中:
Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height); //位图矩形
//以可读写的方式锁定全部位图像素
System.Drawing.Imaging.Bitmap DatabmpData =
curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat);
IntPtr ptr = bmpData.Scan0; //得到首地址
int bytes = curBitmap.Width * curBitmap.Height; //24位BMP位图字节数
byte[] rgbValues = new byte[bytes * 3]; //定义位图数组
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes * 3); //复制被锁定的位图像素到位图数组
3 基于C#的颜色空间转换
RGB和HSI的相互转换公式有不同的形式,但基本思想是相同的,以下是由RGB到HSI转换的一种形式。给定一幅RGB彩色图像,色度分量H依据B和G的关系而定,当B≤G时,H=arccos{0.5×[ (R-G)+(R-B) ]÷[(R-G)2+ (R-B)2+ (G-B)2]0.5},当B>G时,H=2π- arccos{0.5×[ (R-G)+(R-B) ]÷[(R-G)2+ (R-B)2+ (G-B)2]0.5};饱和度分量S=1-[3÷(R+G+B)]×[min(R,G,B)];亮度分量I=(R+G+B)÷3。
在这一转换过程中,H是R、G和B经非线性变换而得到的。如果RGB的值是归一化到[0,1]范围内,则HSI的S和I两个分量的值也在[0,1]范围内,H可以根据上面公式得到的值除以2π归一化到[0,1]范围内。以下是C#实现。
double[] hue = new double[bytes];//色度分量
double[] sat = new double[bytes];//饱和度分量
byte[] inten = new byte[bytes];//亮度分量
double r, g, b;
for (int i = 0; i < bytes; i++)
{r = rgbValues[i * 3 + 2];
g = rgbValues[i * 3 + 1];
b = rgbValues[i * 3];
double theta = Math.Acos(0.5 * ((r - g) + (r - b)) / Math.Sqrt((r - g) * (r - g) + (r - b) * (g - b) + 1)) / (2 * Math.PI);
hue[i] = ((b <= g) ? theta : (1 - theta));
sat[i] = 1.0 - 3.0 * Math.Min(Math.Min(r, g), b) / (r + g + b + 1);
inten[i] = (byte)((r + g + b) / 3);}
由HIS到RGB的转换类似,这里省略了这些公式和C#实现的描述。
4 小结
数字图像处理研究和软件开发的重点在于算法,为了降低难度和提高效率,C#比较适合用来实现、验证和开发这些算法。正如上面介绍的内存方法,把图像复制到内存,直接对内存中的数据进行处理,运行速度也快,开发效率也高;通过验证,算易做图确而有效,也可以将其转化为指针方法来满足更高速度的要求(比如实时处理的要求)。
参考文献:
[1] 龚声蓉.数字图像处理与分析[M].北京:清华大学出版社,2006.
[2] 冈萨雷斯.数字图像处理[M].北京:电子工业出版社,2009.
补充:软件开发 , C# ,