项目笔记---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图片处理的更多相关文章
- Django商城项目笔记No.4用户部分-注册接口-图片验证码
Django商城项目笔记No.4用户部分-注册接口-图片验证码 1.首先分析注册业务接口 1.1.分析可得,至少这么几个接口 图片验证码 短信验证码 用户名是否存在 手机号是否存在 整体注册接口 图片 ...
- [置顶] iOS学习笔记47——图片异步加载之EGOImageLoading
上次在<iOS学习笔记46——图片异步加载之SDWebImage>中介绍过一个开源的图片异步加载库,今天来介绍另外一个功能类似的EGOImageLoading,看名字知道,之前的一篇学习笔 ...
- Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid
Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid 上一步获取QQ登录网址之后,测试登录之后本该跳转到这个界面 但是报错了: 新建oauth_callback.html & ...
- Django商城项目笔记No.6用户部分-注册接口-短信验证码实现celery异步
Django商城项目笔记No.4用户部分-注册接口-短信验证码实现celery异步 接上一篇,如何解决前后端请求跨域问题? 首先想一下,为什么图片验证码请求的也是后端的api.meiduo.site: ...
- Django商城项目笔记No.5用户部分-注册接口-短信验证码
Django商城项目笔记No.4用户部分-注册接口-短信验证码 短信验证码也保存在redis里(sms_code_15101234567) 在views中新增SMSCodeView类视图,并且写出步骤 ...
- JavaScript把项目本地的图片或者图片的绝对路径转为base64字符串、blob对象在上传
主题: JavaScript把项目本地的图片或者图片的绝对路径转为base64字符串.blob对象在上传. 用处: 从本地选择图片上传,如项目规定只能选择本项目文件夹下的图像上传为头像等. 主要思想: ...
- 《BI项目笔记》——微软BI项目笔记连载
本系列文章主要是结合实际项目,加上自己的总结,整理出来的一系列项目笔记,涉及微软SQL Server2008中商务智能开发中的SSAS.SSIS模块: 准备工作: <BI项目笔记>基于雪 ...
- vue项目打包后图片路径问题
当用vue-cli自动构建项目后,有两种运行方法,分别是: npm run dev : 提供一个开发的环境,自动热更新,资源使用绝对路径,所以可以正常看到背景图片. npm run build : 打 ...
- Django商城项目笔记No.11用户部分-QQ登录1获取QQ登录网址
Django商城项目笔记No.11用户部分-QQ登录 QQ登录,亦即我们所说的第三方登录,是指用户可以不在本项目中输入密码,而直接通过第三方的验证,成功登录本项目. 若想实现QQ登录,需要成为QQ互联 ...
随机推荐
- nodejs http静态服务器
使用nodejs写的很简单的静态服务器,没有做cluster处理,没有做缓存处理,不支持访问文件夹,功能只有一个,就是获取到文件后再返回文件内容. var fs = require('fs'); va ...
- ASP.Net中上传文件的几种方法
在做Web项目时,上传文件是经常会碰到的需求.ASP.Net的WebForm开发模式中,封装了FileUpload控件,可以方便的进行文件上传操作.但有时,你可能不希望使用ASP.Net中的服务器控件 ...
- Android SystemUI源代码分析和修改
1.在导航栏中添加音量加减button 一些Android音量调节button.或者从保护实体按键的角度考虑,就须要在导航栏的虚拟按键中加入音量加减调节按键. 效果例如以下图所看到的: 实现步骤例如以 ...
- DNSserver内置笔记本
DNS于linuxserver该服务名是named,和named服务相关的软件bind. 周围环境: 系统版本号:VBOX虚拟机centos6.0. 本机内网IP 192.168.2.198. ...
- C#动态调用WCF接口
C#动态调用WCF接口 写在前面 接触WCF还是它在最初诞生之处,一个分布式应用的巨作. 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项 ...
- SVN和Git的一些用法总结(转)
转载请注明出处:http://www.codelast.com/ 以下都是比较基础的操作,高手们请绕道,不必浪费时间来看了. (A)SVN (1)查看日志提交的时候一般会写上注释,如果要查看提交日志, ...
- Python标准库:内置函数format(value[, format_spec])
的值的函数value按format_spec的格式来格式化,然而函数解释format_spec是依据value的类型来决定的.不同的类型有不同的格式化解释. 当參数format_spec为空时,本函数 ...
- Writing your first Django app, part 1(转)
Let’s learn by example. Throughout this tutorial, we’ll walk you through the creation of a basic pol ...
- MP4文件格式具体解释——结构概述
MP4文件格式具体解释(ISO-14496-12/14) Author:Pirate Leo Email:codeevoship@gmail.com 一.基本概念 1. 文件,由很多Box和FullB ...
- Android Widget 小部件(四---完结) 使用ListView、GridView、StackView、ViewFlipper展示Widget
官方有话这样说: A RemoteViews object (and, consequently, an App Widget) can support the following layout cl ...