图像处理入门

简单的图像处理可以设置图片的每一个像素的RGB值,c#中的代码如下(下面的代码效率不高,只是为了叙述方便,比较高效的代码在最后):

public delegate Color ChangeColor(Color color);

public void ChangeBitmap(ref Bitmap bmp, ChangeColor changeColor)
{
    for (int y = 0; y < bmp.Height; y++)
    {
        for (int x = 0; x < bmp.Width; x++)
        {
            Color color = bmp.GetPixel(x, y);// 得到(x,y)像素点的颜色
            Color newColor = changeColor(color);// 改变这个颜色的rgb
            bmp.SetPixel(x, y, newColor); // 将(x,y)像素的设置成新的颜色
        }
    }
}


色彩通道

屏蔽R、G、B中的某个通道就是将图片中的每个像素的该通道值设为0。比如屏蔽红色和蓝色通道,提取绿色通道,只需要把每个像素的R和B的值设为0,G的值不变:

ChangeBitmap(ref bmp, (color) => { return Color.FromArgb(0, color.G, 0); });

 图像处理入门



色彩平衡调节

增减某些通道的值,比如要减少蓝色通道的数值,增加红色通道的数值:

ChangeBitmap(ref bmp, (color) => {
                int r = color.R + 30;
                if (r > 255) r = 255;
                int b = color.G - 30;
                if (b < 0) b = 0;
                return Color.FromArgb(r,color.G,b); 
            }
        );

 图像处理入门



亮度调节

亮度调节是色彩调节的一个特例,RGB同时增减相同的值

ChangeBitmap(ref bmp, (color) => {
                int r = color.R - 50; if (r < 0) r = 0;
                int g = color.G - 50; if (g < 0) g = 0;
                int b = color.B - 50; if (b < 0) b = 0;
                return Color.FromArgb(r, g, b);
                }
            );

图像处理入门 




对比度调节

提高对比度是让亮(数值大于128)的更亮,暗(数值小于128)的更暗;减少对比度则是增加暗的,减小亮的,让它们都趋于128。一般的算法是按比例调节数值与128相差的那一部分

int degree = 30;//对比度调设为30,0表示没有变化
double contrast = (100.0 + degree) / 100.0;
contrast *= contrast;
ChangeBitmap(ref bmp, (color) => {                
    double r = ((color.R / 255.0 - .5) * contrast + .5) * 255;
    if (r > 255) r = 255; if (r < 0) r = 0;
    //同样方法计算G和B的值
    double g = ...
    double b = ...
    return Color.FromArgb((byte)r, (byte)g, (byte)b);                
    }
);

图像处理入门 




灰度

当RGB三个数值相同时,颜色是灰色的。比如R=G=B=255是白色;R=G=B=0是黑色;在R=G=B=x,x在0~255之间就是灰色的。将彩色图片变成灰白图片就是让R=G=B=x,x的值有多种算法。

ChangeBitmap(ref bmp, (color) => {
        //平均值算法:
        //int x = (color.R + color.G + color.B) / 3;

        //最大值算法:
        //int x = Math.Max(Math.Max(color.R, color.G), color.B);

        //加权平均值算法,人眼对颜色的敏感度:绿色>红色>蓝色,这种算法比较合理:
        double x = 0.3 * color.R + 0.59 * color.G + 0.11 * color.B;
        return Color.FromArgb((byte)x, (byte)x, (byte)x);                
    }
);

图像处理入门 




双色阈值处理

将图片灰度化之后,灰度为大于x的设为前景色,灰度小于x的设为背景色。一般前景色和背景色是白和黑。

这与灰度化处理是有区别的。阈值处理后只有两种颜色,而灰度化处理后有0~255共256种灰度颜色

Color foreground = Color.Yellow;
Color background = Color.Black;
int threshold = 128;//阈值
ChangeBitmap(ref bmp, (color) => {
        int gray = (color.R + color.G + color.B) / 3;//先灰度化
        if (gray > threshold)
            return foreground;
        else return background;
    }
);

图像处理入门 




底片

将RGB的值分别用255去减,就的到底片效果的图片

ChangeBitmap(ref bmp, (color) => {
    return Color.FromArgb(255 - color.R, 255 - color.G, 255 - color.B);
    }
);

图像处理入门 




伪色彩

灰白的图像理论上是不能还原为原始的色彩图像的。伪色彩是将不同灰度的颜色映射成其他色彩,映射的算法可以自己定。

由于人眼对色彩的分辨率远高于对灰度差的分辨率,所以进行这种转换能使图像中的信息更容易辨认。比如灰度相差很小的两种灰色不好分辨,如果把这两种颜色分别变成红色和蓝色就很好分辨了。

以下是其中的一种映射算法: 

ChangeBitmap(ref bmp, (color) => {
        int x = color.R;//对于灰白图像,RGB的值一样
        int r=0, g=0, b=0;
        switch (x >> 6)
        {
            case 0:
                r = 0;
                g = 4 * x;
                b = 255;
                break;

            case 1:
                r = 0;
                g = 255;
                b = 511 - 4 * x;
                break;

            case 2:
                r = 4 * x - 511;
                g = 255;
                b = 0;
                break;

            case 3:
                r = 255;
                g = 1023 - 4 * x;
                b = 0;
                break;
        }
        return Color.FromArgb(r, g, b);
    }
);

 图像处理入门

 

Gamma矫正

由于显卡或显示去的原因实际输出的图像在亮度上可以会有偏差,像素的亮度值可能与实际显示的亮度有差别。Gamma矫正是用来矫正这种偏差,应该算是一种特殊的亮度映射吧。一般用来平滑的拓展暗调的细节。但矫正值大于1时,图像高亮部分被压缩而暗调部分被拓展,造成输出亮化;矫正值小于1时则相反,造成输出暗化。

double degree = 2;// 矫正量 0.1~5.0
// 建立Gamma矫正映射表
double g = 1 / degree;
byte[] gamma = new byte[256];
for (int i = 0; i < 256; i++)
{
    int pixel = (int)((255.0 * Math.Pow(i / 255.0, g)) + 0.5);
    gamma[i] = (byte)(pixel > 255 ? 255 : pixel);
}

ChangeBitmap(ref bmp, (color) => {
            return Color.FromArgb(gamma[color.R], gamma[color.G], gamma[color.B]);
        }
    );





  •  以上使用 代理和Lambda 表达式的代码执行速度较慢,实际中可以使用c#中unsafe不安全代码,直接操作指针,可以提高效率:

public void ChangeBitmap(ref Bitmap bmp)
{
    int width = bmp.Width;
    int height = bmp.Height;    
    BitmapData data = bmp.LockBits(new Rectangle(new Point (0,0),bmp.Size),ImageLockMode.ReadWrite,bmp.PixelFormat);
    int bpp = 3;
    int offset = data.Stride - bpp * width;
    unsafe
    {
        byte* p = (byte*)data.Scan0;
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                // 设置每个像素的rgb值
                // p[2] 红色
                // p[1] 绿色
                // p[0] 蓝色

                p += bpp;
            }
            p += offset;
        }
    }
    bmp.UnlockBits(data);
}

 


以上内容主要参考《图像编程精髓——从开发自己的Photoshop开始》

你可能感兴趣的:(图像处理,通道,灰度,对比度,亮度,伪色彩)