玩玩图形图像——第一篇:图片灰度化

 

    去年买了本数字图像处理算法,一直都没有看,前几个星期都一直忙着工作上的活,趁这阶段悠闲点,玩一玩图片处理,这玩意

还是非常有意思的。

   以前我们在做Web上的用户注册时,通常都会做一个验证码,大家都知道用来防止暴力注册的,当然提到验证码大家都知道C#里

面有一个Bitmap类专门用来处理图片的,好吧,这一篇我们从最简单的“图片灰度化”说起。

一:图片灰度化

     我们都知道,位图是由一个一个像素点组成的,像素点可能是红色,橙色,粉色等等,这些颜色我们都知道是用RGB来表示的。

每个颜色分量都是一个字节(0-255),所以一般情况下图的像素点都是24位,当然还有32位,64位,当RGB是0-255之间的不同值

时,那么该像素点就呈现“五颜六色”,而当RGB都是相同的值是,则像素点呈现“灰色”,如果大家玩过CSS的话,肯定都知道给一个

字体的color通常都是#999999,#666666,#333333这些不同深度的灰色。

1.计算公式

   下面我们该如何设置合理的灰度值呢?当然还是用当前的RGB为模板,然后对RGB乘以一个合理的权重就ok了

   Gary(i,j)=0.299*R(i,j)+0.587*G(i,j)+0.114*B(i,j);

2.编程

  有了公式,实现起来就不成问题了。Bitmap类中有一个GetPixel/SetPixel,它可以获取和设置当前的像素点。

static void Main(string[] args)
{
    Bitmap bitmap = new Bitmap(Environment.CurrentDirectory + "//1.jpg");

    for (int i = 0; i < bitmap.Width; i++)
    {
        for (int j = 0; j < bitmap.Height; j++)
        {
            //取图片当前的像素点
            var color = bitmap.GetPixel(i, j);

            var gray = (int)(color.R * 0.299 + color.G * 0.587 + color.B * 0.114);

            //重新设置当前的像素点
            bitmap.SetPixel(i, j, Color.FromArgb(gray, gray, gray));
        }
    }

    bitmap.Save(Environment.CurrentDirectory + "//2.jpg");
}

  

3.改进

   上面这个方法很简单,Get/Set就Ok了,当然这是我们站在像素点这个角度来考虑问题的,貌似只要O(N2)的时间就可以KO问

题,但是Get/Set远远不是O(1)的,基于性能考虑,我们能不能有更优的方法,此时我们可以站在字节这个角度思考,不过这里我

们要注意一个问题就是:比如图片的width=21px,一个像素点占用3个字节,但是21个像素点不一定就占用63个字节,这是因为

系统基于性能考虑,在每一行中存放着一个“未用区域”,来确保图片每行的byte数是4的倍数,那么如何去读某一行的字节数呢?

C#里面有一个Stride属性就可以用来获取,很简单吧。

static void Main(string[] args)
        {
            Bitmap bitmap = new Bitmap(Environment.CurrentDirectory + "//1.jpg");

            //定义锁定bitmap的rect的指定范围区域
            Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);

            //加锁区域像素
            var bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, bitmap.PixelFormat);

            //位图的首地址
            var ptr = bitmapData.Scan0;

            //stride:扫描行
            int len = bitmapData.Stride * bitmap.Height;

            var bytes = new byte[len];

            //锁定区域的像素值copy到byte数组中
            Marshal.Copy(ptr, bytes, 0, len);

            for (int i = 0; i < bitmap.Height; i++)
            {
                for (int j = 0; j < bitmap.Width * 3; j = j + 3)
                {
                    var color = bytes[i * bitmapData.Stride + j + 2] * 0.299
                                + bytes[i * bitmapData.Stride + j + 1] * 0.597
                                + bytes[i * bitmapData.Stride + j] * 0.114;

                    bytes[i * bitmapData.Stride + j]
                             = bytes[i * bitmapData.Stride + j + 1]
                             = bytes[i * bitmapData.Stride + j + 2] = (byte)color;
                }
            }

            //copy回位图
            Marshal.Copy(bytes, 0, ptr, len);

            //解锁
            bitmap.UnlockBits(bitmapData);

            bitmap.Save(Environment.CurrentDirectory + "//3.jpg");
        }

  

 

时间: 2024-08-28 04:53:46

玩玩图形图像——第一篇:图片灰度化的相关文章

【实战HTML5与CSS3 第一篇】初探水深,美丽的导航,绚丽的图片爆炸!!

原文http://www.cnblogs.com/yexiaochai/archive/2013/04/29/3050798.html 前言 先八卦一下,我昨天离职了,把电脑也退了,离职前,我发了一封邮件给整个部门,陈述自己的不舍与团队管理问题(估计传说中的leader要抓狂了),然后就昏昏的回家了,所以昨天没有什么产出. 最近经常有朋友惊叹我的发帖速度很快,其实是有原因的,我最近两周要离职,所以就不太理我那传说中的leader了,每天多出很多时间可以学习. 但是,下周后便会入职一家新公司了,我

c#图像灰度化、灰度反转、二值化

图像灰度化:将彩色图像转化成为灰度图像的过程成为图像的灰度化处理.彩色图像中的每个像素的颜色有R.G.B三个分量决定,而每个分量有255中值可取,这样一个像素点可以有1600多万(255*255*255)的颜色的变化范围.而灰度图像是R.G.B三个分量相同的一种特殊的彩色图像,其一个像素点的变化范围为255种,所以在数字图像处理种一般先将各种格式的图像转变成灰度图像以使后续的图像的计算量变得少一些.灰度图像的描述与彩色图像一样仍然反映了整幅图像的整体和局部的色度和亮度等级的分布和特征.图像的灰度

安卓LibGDX游戏引擎开发教程(六) 图形图像的绘制(下)图片整合工具的使用

在上一篇文章中,我们提到了图片必须是2的n次方的问题.但是随着Libgdx的不断完善和发展,使用一些 工具就可以很好的解决了这样一个问题,但是它的功能又不仅仅只限于此,那么下面就来让我们看看 TexturePacker-Gui工具的使用,我们又称之它为图片整合工具. 一.TexturePacker-Gui简介 TexturePacker-Gui是一个可视化版本的图片整合工具.这个工具的用途很简单,就是一个将小 图片整合成一张大图片,在把大图片打包成可查找的图片.而且通过TexturePacker

编程c语言-求一个把bmp图像灰度化并把灰度化后的像素存入数组里的C语言函数,不用opencv

问题描述 求一个把bmp图像灰度化并把灰度化后的像素存入数组里的C语言函数,不用opencv 求一个把bmp图像灰度化并把灰度化后的像素存入数组里的C语言函数,不用opencv 解决方案 顶顶顶顶顶顶顶顶顶顶

用opencv4android中的cvtColoer()对图像灰度化后,为什么像素值都是负数?

问题描述 用opencv4android中的cvtColoer()对图像灰度化后,为什么像素值都是负数? Imgproc.cvtColor(srcMat grayMat Imgproc.COLOR_RGB2GRAY);我是这样灰度化的然后,graybmp = Bitmap.createBitmap(bmp.getWidth() bmp.getHeight() Config.RGB_565);Utils.matToBitmap(grayMat graybmp);我转成bmp图像随后,graybmp

安卓LibGDX游戏引擎开发教程(五)图形图像的绘制(上)基础类的使用和详解

由于平常工作和生活琐事的种种原因,所以这个系列的教程更新的有点慢,还请大家见谅.在这期的主题 中,博主给大家来的教学是关于图形图像的绘制,要知道一个最基本的应用程序都会有一个精美的图像,那么 就更别说一个成功的游戏了,首先要有绚丽的图片背景才是吸引玩家试玩的关键,不是嘛? 在这篇文 章中主要讲解到的有Texture.SpriteBatch.Sprite和Pixmap这四个类. 一.Texture和SpriteBatch 类 1.Texture介绍 我们先来看一下官方API文档,如下图所示: 开发

CoreOS Fest 系列之第一篇:容器江湖

本文讲的是CoreOS Fest 系列之第一篇:容器江湖,[编者的话] 这是总结 CoreOS Fest 大会的三篇文章之一,主要介绍了 CoreOS 公司与 Docker 公司之争,新成立的 appc 规范委员会, Tectonic 平台, Kubernetes 项目. 最近在旧金山, Linux 容器已经显得非常有「钱」景,看起来每个人都想从这个有几十亿美金规模的新市场中分得一杯羹.多家创业公司和云主机公司已经或者即将召开有关容器的大会,包括 4 月 17 日召开的 Container Ca

C#图片灰度处理(位深度24→位深度8),用灰度数组byte[]新建一个8位灰度图像Bitmap 。

原文:C#图片灰度处理(位深度24→位深度8) #region 灰度处理 /// <summary> /// 将源图像灰度化,并转化为8位灰度图像. /// </summary> /// <param name="original"> 源图像. </param> /// <returns> 8位灰度图像. </returns> public static Bitmap RgbToGrayScale(Bitmap o

一步一步学Silverlight :图形图像综合实例---实现水中倒影效果

概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, Ironpython,对JSON.Web Service.WCF以及Sockets的支持等一系列新的特性.<一步一步学Silverlight 2系列>文章将从Silverlight 2基础知识.数据与通信.自定义控件.动画.图形图像等几个方面带您快速进入Silverlight 2开发. 本文将综