c#中实现图片灰度化技术详解

 更新时间:2020年6月25日 11:35  点击:2179

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

以前我们在做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");
    }

[!--infotagslink--]

相关文章

  • C#实现简单的登录界面

    我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
  • 浅谈C# 字段和属性

    这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
  • 使用PHP+JavaScript将HTML页面转换为图片的实例分享

    这篇文章主要介绍了使用PHP+JavaScript将HTML元素转换为图片的实例分享,文后结果的截图只能体现出替换的字体,也不能说将静态页面转为图片可以加快加载,只是这种做法比较interesting XD需要的朋友可以参考下...2016-04-19
  • C#中截取字符串的的基本方法详解

    这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
  • C#实现简单的Http请求实例

    这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
  • C#连接SQL数据库和查询数据功能的操作技巧

    本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
  • C#中new的几种用法详解

    本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
  • 使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)

    这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#开发Windows窗体应用程序的简单操作步骤

    这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
  • C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
  • Photoshop古装美女图片转为工笔画效果制作教程

    今天小编在这里就来给各位Photoshop的这一款软件的使用者们来说说把古装美女图片转为细腻的工笔画效果的制作教程,各位想知道方法的使用者们,那么下面就快来跟着小编一...2016-09-14
  • Python 图片转数组,二进制互转操作

    这篇文章主要介绍了Python 图片转数组,二进制互转操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-09
  • C#和JavaScript实现交互的方法

    最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • 轻松学习C#的基础入门

    轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
  • php抓取网站图片并保存的实现方法

    php如何实现抓取网页图片,相较于手动的粘贴复制,使用小程序要方便快捷多了,喜欢编程的人总会喜欢制作一些简单有用的小软件,最近就参考了网上一个php抓取图片代码,封装了一个php远程抓取图片的类,测试了一下,效果还不错分享...2015-10-30
  • C#变量命名规则小结

    本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
  • C#绘制曲线图的方法

    这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
  • c#自带缓存使用方法 c#移除清理缓存

    这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25