原文:项目笔记---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. Cloudera impala简单介绍及安装具体解释

    一.Impala简单介绍 Cloudera Impala对你存储在Apache Hadoop在HDFS,HBase的数据提供直接查询互动的SQL.除了像Hive使用同样的统一存储平台,Impala也使 ...

  2. 这个夏天不AC(杭州电2037)

    这个夏天不AC Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Su ...

  3. android代码签名和混乱的包装

    研究了一下android的apk困惑签名和代码包装,假设没有混乱包.然后apk人们可以直接查看源代码反编译出来,尽管混乱包或能看懂.但不是那么容易理解,要求在至少一些时间 假设不混淆,反编译后的代码例 ...

  4. 24L01/SI24R1调试笔记

    1.SPI MSB优先,8Bit寄存器地址与内容: 2.寄存器结构与之前使用的LT8900不同,分为R.W寄存器与特殊功能寄存器: 3.特别注意:在TX.RX.RT中断或者轮询后置1,必须写1清零与清 ...

  5. [.Net Tools] 超強大的封裝工具 Advanced Installer

    原文:[.Net Tools] 超强大的封装工具Advanced Installer 日前在网路上晃到这家公司的产品http://www.advancedinstaller.com/,就直接下载并且安 ...

  6. win9x_win2k下对物理磁盘的操作

    void CReadSectorDlg::OnReadButton() { UpdateData (TRUE) ; CFile m_Sector_file ; char * buffer ; if ( ...

  7. 翻译器DIY它———算在英文文本中的单词数,字符和行数

    咳咳.这部分应该是序列化编译器DIY的,然而,在这样做DIY第一次使用前flex 为了练练手,对于后者的理解是有帮助. 在word 我经常看到一个字计数功能,因此,它是如何实现,当然,首先想到的是要经 ...

  8. 通过.NET实现后台自动发送Email功能的代码示例

    原文:通过.NET实现后台自动发送Email功能的代码示例 通过.NET实现后台自动发送邮件功能的代码,可以将一些基础信息放到web.config文件中进行保存: Web.config文件信息段: & ...

  9. Git提交代码的处理流程(转)

    Jerry 工作在wchar_support分支.他改变了名称的功能和测试后,他提交他的变化. [jerry@CentOS src]$ git branch master * wchar_suppor ...

  10. 划分数 (DP)

    输入: n=4 m=3 M=10000 输出: 4 (1+1+2=1+3=2+2=4) 复杂度(nm) int n,m; int a[MAX]; int dp[MAX][MAX]; //数组 void ...