原文:项目笔记---CSharp图片处理

项目笔记---CSharp图片处理

最近由于项目上需要对图片进行二值化处理,就学习了相关的图片处理上的知识,从开始的二值化的意义到动态阀值检测二值化等等,并用C#得以应用,学到了很多的知识和大家分享下我个人的经验,希望对大家有帮助。

二值化

二值化简而言之是对一副彩色图片进行0/1运算,最终显示一副黑白相间的图片,其意义多数在于对二值化处理后的图片进行分割识别,一些自动识别的验证码工具大多是先进行二值化,然后在模式识别,最终推断出验证码;我的项目中是由于硬件只支持黑色和白色,所以要对用户的图片进行处理,然后显示在硬件上。

在深入了解二值化的过程中就发现了很多有意思,或者说十分令我感兴趣的东西,就是各种图片处理算法。

因为一个普通,色彩少,图像相对简单的图片经二值化处理后还算能勉强接受。但是一副精美的图片在经过二值化处理后显得十分难看,或根本看不出图片有任何意义。这其中大家就开始研究思考。

先补充下知识,因为我觉得如果不把基本原理讲清楚的话,可能大家不会发现这些算法是多么的有意思(当然,也可能是我太喜欢这些东西而已)。过程是这样的,一副彩色的图片要先进行灰度化(有的是 将R+G+B加起来除以3取平均值再付给R=G=B,也可以依据权值进行灰度划分,如(0.299 * r + 0.587 * g + 0.114 * b) 这是一个依据人眼对不同RGB颜色的区分度进行优化的灰度算法,很有意思,想不到人类对不同颜色识别轻重还不一样)。在经过灰度化之后,实际每个颜色的色值是 R=G=B=(0-255之间)的数值,这样我们当然可以依据127划分,如果小于127则认为接近黑色0,反之则认为接近白色255,将所有色值依据127划分后图像就成为黑白的二值化图片。

回过头来,我们来看看,这样经过二值化处理的图片“失真”还是很严重,有没有什么办法能优化呢,当然这难不倒这些研究算法的专家们。

Ordered dithering有序抖动就是一个化腐朽为神奇的算法,具体算法细节不去深究,大概就是依据一个算法矩阵,然后对图像点进行处理。下面是图片对比。

这幅图片是原图

这幅图是已128为全局阀值的二值化图片

这幅图是有序抖动处理后的二值化图片,黑白的二值化图片(并非灰度),所有的点非黑即白,视觉上会产生灰度图片的视觉误差,这就是神奇之处。(注:原图如果是大图的话,效果更明显。)

此外,还有很多优秀的算法对图片进行处理,大都是围绕如何处理判断“阀值”而产生的。

AForge.Net.Image

在查找C#开源类库的时候,发现了强大的AForge.Net,您可以先参考其官方网站了解更多详情。这个开源类库实在是太强大了,不仅包含图片处理的各种算法方式,视频处理方式,还包含人工智能方面的各种实践,都是基于C#写的,代码整洁程度也是值得学习的,所以,今后如果有时间应该仔细研究研究。而且官方文档及Sample都十分完善,十分强大。

N多种图片处理方式,参照Demo,你会发现使用起来极其简单~~

代码样例

啰嗦了那么多,下面就演示下代码如何实现的:

这里代码可能不全,请参照官方AForge.NET Framework-2.2.5\Samples\Imaging\FiltersDemo这个Demo

Bitmap temp = AForge.Imaging.Image.Clone(new Bitmap(SrcPic), PixelFormat.Format24bppRgb); // 加载图片,并强制转换成Format24bppRgb这种格式

temp = Grayscale.CommonAlgorithms.RMY.Apply(temp); // 将图片依照RY算法进行灰度化,很多算法都是先灰度然后再处理的。

pictureBox.Image =(new OrderedDithering()).Apply(sourceImage); // 应用Filter,这里选取OrderedDithering类型的Filter

这是应用AForge.Net实现的多种处理图片的代码,很简单并且扩展性很强,值得学习。

更多代码请参考官方Sample,有任何问题,请回复我。

后记

虽然有了十分强大的AForge.Net,但是针对一些特定图片处理需求还是要自己写代码的,当然也可以用AForge实现,这里我只是强调一下如果自己手动写代码的话是如何处理的并且有哪些需要注意的地方。

首先从彩色图片灰度化说起:所谓灰度化就是按照一定的算法将R,G,B的值转换成同一个值,这其中比较普遍的做法一个是(R+G+B)/3取平均值,另一个是加权算法依据人眼对不同颜色的识别而权值化的算法 (0.299 * r + 0.587 * g + 0.114 * b) = R=G=B。

        /// <summary>
/// 灰度化实现
/// </summary>
/// <param name="bmp"></param>
/// <param name="foo"></param>
/// <returns></returns>
private static Bitmap WeightGrayScaleImple(Bitmap bmp, Func<double, double, double, byte> foo)
{
Bitmap thisMap = bmp;
Rectangle rect = new Rectangle(, , thisMap.Width, thisMap.Height);
BitmapData bmpData = thisMap.LockBits(rect, ImageLockMode.ReadWrite, thisMap.PixelFormat);
unsafe
{
byte* ptr = (byte*)(bmpData.Scan0);
for (int i = ; i < bmpData.Height; i++)
{
for (int j = ; j < bmpData.Width; j++)
{
ptr[] = ptr[] = ptr[] = foo(ptr[], ptr[], ptr[]);
ptr += ;
}
ptr += bmpData.Stride - bmpData.Width * ;
}
}
thisMap.UnlockBits(bmpData);
return thisMap;
}
        
     // Foo 实现
     private static byte WeightGrayBinaraztion(double r, double g, double b)
{
return (byte)(0.299 * r + 0.587 * g + 0.114 * b);// Feature Weight
}

注:在C#下对图片值这种指针类型的处理时,必须启用unsafe,否则效率极其低。(项目中打开unsafe开关:项目属性--->生成--->允许不安全代码)

基本上以上内容就是项目中所用到的处理图片的所有内容,希望通过以上内容的介绍对大家有帮助。 有问题,欢迎回复,谢谢。

Reference

http://en.wikipedia.org/wiki/Ordered_dithering

http://www.aforgenet.com/aforge/framework/

项目笔记---CSharp图片处理的更多相关文章

  1. Django商城项目笔记No.4用户部分-注册接口-图片验证码

    Django商城项目笔记No.4用户部分-注册接口-图片验证码 1.首先分析注册业务接口 1.1.分析可得,至少这么几个接口 图片验证码 短信验证码 用户名是否存在 手机号是否存在 整体注册接口 图片 ...

  2. [置顶] iOS学习笔记47——图片异步加载之EGOImageLoading

    上次在<iOS学习笔记46——图片异步加载之SDWebImage>中介绍过一个开源的图片异步加载库,今天来介绍另外一个功能类似的EGOImageLoading,看名字知道,之前的一篇学习笔 ...

  3. Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid

    Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid 上一步获取QQ登录网址之后,测试登录之后本该跳转到这个界面 但是报错了: 新建oauth_callback.html & ...

  4. Django商城项目笔记No.6用户部分-注册接口-短信验证码实现celery异步

    Django商城项目笔记No.4用户部分-注册接口-短信验证码实现celery异步 接上一篇,如何解决前后端请求跨域问题? 首先想一下,为什么图片验证码请求的也是后端的api.meiduo.site: ...

  5. Django商城项目笔记No.5用户部分-注册接口-短信验证码

    Django商城项目笔记No.4用户部分-注册接口-短信验证码 短信验证码也保存在redis里(sms_code_15101234567) 在views中新增SMSCodeView类视图,并且写出步骤 ...

  6. JavaScript把项目本地的图片或者图片的绝对路径转为base64字符串、blob对象在上传

    主题: JavaScript把项目本地的图片或者图片的绝对路径转为base64字符串.blob对象在上传. 用处: 从本地选择图片上传,如项目规定只能选择本项目文件夹下的图像上传为头像等. 主要思想: ...

  7. 《BI项目笔记》——微软BI项目笔记连载

    本系列文章主要是结合实际项目,加上自己的总结,整理出来的一系列项目笔记,涉及微软SQL Server2008中商务智能开发中的SSAS.SSIS模块:  准备工作: <BI项目笔记>基于雪 ...

  8. vue项目打包后图片路径问题

    当用vue-cli自动构建项目后,有两种运行方法,分别是: npm run dev : 提供一个开发的环境,自动热更新,资源使用绝对路径,所以可以正常看到背景图片. npm run build : 打 ...

  9. Django商城项目笔记No.11用户部分-QQ登录1获取QQ登录网址

    Django商城项目笔记No.11用户部分-QQ登录 QQ登录,亦即我们所说的第三方登录,是指用户可以不在本项目中输入密码,而直接通过第三方的验证,成功登录本项目. 若想实现QQ登录,需要成为QQ互联 ...

随机推荐

  1. Visual Studio Team Services使用教程--Readers tfs组checkin权限修改

    你也可以只开启部分代码的权限 把上面开启的整个应用的权限先去掉 只开启一个文件的权限

  2. Serializable 作用

    Serializable 作用 序列化的attribute,是为了利用序列化的技术 准备用于序列化的对象必须设置 [System.Serializable] 标签,该标签指示一个类能够序列化. 便于在 ...

  3. ExtJs4得知(五岁以下儿童)主要的Ext分类

    Ext类是ExtJs最常见的.最基本的类,它是一个全局对象,它封装了全班.辛格尔顿和 Sencha 该方法提供了一种有用的库. 嵌套在该命名空间中一个较低的水平最用户界面组件. 但是提供了很多有用的功 ...

  4. 百度echarts扇形图每个区块增加点击事件

    效果图:操作人员要求 :我想看这个扇形图对应的 页面信息,给我加个链接跳转:原先的chart.js发现没有api,后来改用百度的echart.js <!DOCTYPE html> < ...

  5. debian 该分区的部分安装移动硬盘后无法识别。

    有一个新的团购1T移动硬盘.购买格化学式ntfs经过几次简单的子区域. 4G硬盘PE.100G高速互动,盈800许多G分为两个相等的存储盘. 到您的计算机USB接口后,, 桌面弹出自己主动4一封信. ...

  6. Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质

    原文:Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质 Linux内核分析(六) 昨天我们对字符设备进行了初步的了解,并且实现了简单的字符设备驱动,今天我们继续对字符设备的某些方 ...

  7. Cocos2d-3x:vs2012项目开关android项目需要注意的地方

    http://www.cocoachina.com/bbs/read.php?tid=194668 先依照这个文章导入库到vs项目. 在vs项目的sceen类的里加入 #include "c ...

  8. DDD实践案例:引入事件驱动与中间件机制来实现后台管理功能

    DDD实践案例:引入事件驱动与中间件机制来实现后台管理功能 一.引言 在当前的电子商务平台中,用户下完订单之后,然后店家会在后台看到客户下的订单,然后店家可以对客户的订单进行发货操作.此时客户会在自己 ...

  9. ABP入门教程

    ABP入门教程 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...

  10. Leetcode:unique_binary_search_trees

    一.     称号 给定的数目n.问:有多少种不同BST(二叉搜索树) 比如: 因为N =3,共同拥有5种独特的BST. 1          3      3       2      1 \   ...