原文:项目笔记---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. Cocos2d-x Auto-batching 浅浅的”深入分析”

    Auto-batching是Cocos2d-x3.0新增的特性,目的是为了代替SpriteBatchNode,完毕渲染的批处理,提高绘制效率. 至于它有什么特点,能够看看官方文档,这里主要想探讨Aut ...

  2. gtest简短,简单易用

    gtest它是一种跨平台的(Liunx.Mac OS X.Windows.Cygwin.Windows CE and Symbian)的C++测试框架.有google该公司宣布. gtest台上为编写 ...

  3. 使用log4j日志-配置载入问题

    1.在eclipse中,把log4j.properties放在类路径下,在项目启动时就会自己主动载入. 2.在idea中.把log4j.properties放在类路径下,可是项目启动时不能直接载入(原 ...

  4. hadoop编程小技巧(7)---自己定义输出文件格式以及输出到不同文件夹

    代码測试环境:Hadoop2.4 应用场景:当须要定制输出数据格式时能够採用此技巧,包含定制输出数据的展现形式.输出路径.输出文件名称称等. Hadoop内置的输出文件格式有: 1)FileOutpu ...

  5. 当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法(转)

    对象的synchronized方法不能进入了,但它的其他非synchronized方法还是可以访问的 对每一个class只有一个thread可以执行synchronized static method ...

  6. 一个好用的web甘特图

      前些天一直在弄web甘特图,发现网上很多web甘特图框架,但大部分是收费的.偶尔发现了向日葵甘特图 感觉不错,特此写下来一方面当做记录,另一方面也为寻找web甘特图的同学们少走一些弯路,双赢嘛~ ...

  7. Online网站集

    http://tool.oschina.net/apidocs/    在线工具(IT技术工具)

  8. cocos2d-x3.2中map的基本操作和使用

    在游戏开发中,我们有时候会用到map,而map的使用方法我简单给大家介绍一下.Map是c++的一个标准容器,她提供了非常好一对一的关系,在一些程序中建立一个map能够起到事半功倍的效果,总结了一些ma ...

  9. 线程池ThreadPoolExecutor使用简介(转)

    一.简介 线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int ...

  10. SVN常见错误两项纪录

    1.svn cleanup failed–previous operation has not finished; run cleanup if it was interrupted 也许前clean ...