C# 内存法图像处理

内存法通过把图像储存在内存中进行处理,效率大大高于GetPixel方法,安全性高于指针法。

笔者当初写图像处理的时候发现网上多是用GetPixel方法实现,提到内存法的时候也没有具体实现,所以笔者在这里具体实现一下- -,望指正。

首先讲一下用到的一些方法。

1.LockBits和UnlockBits:使用 LockBits 方法,可在系统内存中锁定现有的位图,以便通过编程方式进行更改,每调用LockBits之后都应该调用一次UnlockBits。

2.Scan0:图像的第一个字节地址。

3.Stride:步幅,扫描宽度,形象的说就是一行的长度。

4.PixelFormat:数据的实际像素格式。

给出原图:

 

一、灰度

对每个像素点进行加权平均,(方法不唯一)。

        /// <summary>/// 灰化实现方法/// </summary>void Image_Ashing(){if (pbshowbox.Image != null){int Height = this.pbshowbox.Image.Height;int Width = this.pbshowbox.Image.Width;Bitmap bitmap = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);Bitmap MyBitmap = (Bitmap)this.pbshowbox.Image;BitmapData oldData = MyBitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);BitmapData newData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);unsafe{byte* pin = (byte*)(oldData.Scan0.ToPointer());byte* pout = (byte*)(newData.Scan0.ToPointer());for (int y = 0; y < oldData.Height; y++){for (int x = 0; x < oldData.Width; x++){byte Result = (byte)(pin[0] * 0.1 + pin[1] * 0.2 + pin[2] * 0.7);//加权平均实现灰化pout[0] = (byte)(Result);pout[1] = (byte)(Result);pout[2] = (byte)(Result);pin = pin + 3;pout = pout + 3;}pin += oldData.Stride - oldData.Width * 3;pout += newData.Stride - newData.Width * 3;}bitmap.UnlockBits(newData);MyBitmap.UnlockBits(oldData);this.pbshowbox.Image = bitmap;}}else{MessageBox.Show("请先打开一张图片!");}}

二、柔化

像素点与周围像素点差别较大时取平均值。

        /// <summary>/// 柔化实现方法/// </summary>void Image_Soften(){if (pbshowbox.Image != null){int Height = this.pbshowbox.Image.Height;int Width = this.pbshowbox.Image.Width;Bitmap bitmap = new Bitmap(Width, Height, PixelFormat.Format32bppRgb);Bitmap MyBitmap = (Bitmap)this.pbshowbox.Image;BitmapData oldData = MyBitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);BitmapData newData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);unsafe{byte* pin = (byte*)(oldData.Scan0.ToPointer());byte* pout = (byte*)(newData.Scan0.ToPointer());//高斯模板int[] Gauss = { 1, 2, 1, 2, 4, 2, 1, 2, 1 };for (int i = 1; i < Width - 1; i++){for (int j = 1; j < Height - 1; j++){int r = 0, g = 0, b = 0;int Index = 0;for (int col = -1; col <= 1; col++){for (int row = -1; row <= 1; row++){int off = ((j + row) * (Width) + (i + col)) * 4;r += pin[off + 0] * Gauss[Index];g += pin[off + 1] * Gauss[Index];b += pin[off + 2] * Gauss[Index];Index++;}}r /= 16;g /= 16;b /= 16;//处理颜色值溢出if (r < 0) r = 0;if (r > 255) r = 255;if (g < 0) g = 0;if (g > 255) g = 255;if (b < 0) b = 0;if (b > 255) b = 255;int off2 = (j * Width + i) * 4;pout[off2 + 0] = (byte)r;pout[off2 + 1] = (byte)g;pout[off2 + 2] = (byte)b;}}bitmap.UnlockBits(newData);MyBitmap.UnlockBits(oldData);this.pbshowbox.Image = bitmap;}}else{MessageBox.Show("请先打开一张图片!");}}

三、锐化

突出显示颜色值大的像素点。

        /// <summary>/// 锐化实现方法,显示数值最大像素点/// </summary>void Image_Sharpen(){if (this.pbshowbox.Image != null){int Height = this.pbshowbox.Image.Height;int Width = this.pbshowbox.Image.Width;Bitmap bitmap = new Bitmap(Width, Height, PixelFormat.Format32bppRgb);Bitmap MyBitmap = (Bitmap)this.pbshowbox.Image;BitmapData oldData = MyBitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);BitmapData newData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);unsafe{byte* pin = (byte*)(oldData.Scan0.ToPointer());byte* pout = (byte*)(newData.Scan0.ToPointer());//拉普拉斯模板int[] Laplacian = { -1, -1, -1, -1, 9, -1, -1, -1, -1 };for (int i = 1; i < Width - 1; i++){for (int j = 1; j < Height - 1; j++){int r = 0, g = 0, b = 0;int Index = 0;for (int col = -1; col <= 1; col++){for (int row = -1; row <= 1; row++){int off = ((j + row) * (Width) + (i + col)) * 4;r += pin[off + 0] * Laplacian[Index];g += pin[off + 1] * Laplacian[Index];b += pin[off + 2] * Laplacian[Index];Index++;}}if (r < 0) r = 0;if (r > 255) r = 255;if (g < 0) g = 0;if (g > 255) g = 255;if (b < 0) b = 0;if (b > 255) b = 255;int off2 = (j * Width + i) * 4;pout[off2 + 0] = (byte)r;pout[off2 + 1] = (byte)g;pout[off2 + 2] = (byte)b;}}bitmap.UnlockBits(newData);MyBitmap.UnlockBits(oldData);this.pbshowbox.Image = bitmap;}}else{MessageBox.Show("请先打开一张图片!");}}

四、浮雕

对图像像素点的像素值分别与相邻像素点的像素值相减后加上128, 然后将其作为新的像素点的值。

        /// <summary>/// 浮雕实现方法/// </summary>void Image_Relief(){if (this.pbshowbox.Image != null){int Height = this.pbshowbox.Image.Height;int Width = this.pbshowbox.Image.Width;Bitmap bitmap = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);Bitmap MyBitmap = (Bitmap)this.pbshowbox.Image;BitmapData oldData = MyBitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);BitmapData newData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);unsafe{byte* pin_1 = (byte*)(oldData.Scan0.ToPointer());byte* pin_2 = pin_1 + (oldData.Stride);                byte* pout = (byte*)(newData.Scan0.ToPointer());for (int y = 0; y < oldData.Height - 1; y++){for (int x = 0; x < oldData.Width; x++){                           int b = (int)pin_1[0] - (int)pin_2[0] + 128;int g = (int)pin_1[1] - (int)pin_2[1] + 128;int r = (int)pin_1[2] - (int)pin_2[2] + 128;if (r < 0) r = 0;if (r > 255) r = 255;if (g < 0) g = 0;if (g > 255) g = 255;if (b < 0) b = 0;if (b > 255) b = 255;pout[0] = (byte)(b);pout[1] = (byte)(g);pout[2] = (byte)(r);pin_1 = pin_1 + 3;pin_2 = pin_2 + 3;pout = pout + 3;                          }pin_1 += oldData.Stride - oldData.Width * 3;pin_2 += oldData.Stride - oldData.Width * 3;pout += newData.Stride - newData.Width * 3;}bitmap.UnlockBits(newData);MyBitmap.UnlockBits(oldData);this.pbshowbox.Image = bitmap;}}else{MessageBox.Show("请先打开一张图片!");}}

五、底片

颜色值取反。

        /// <summary>/// 底片实现方法/// </summary>void Image_Negative(){if (pbshowbox.Image != null){int Height = this.pbshowbox.Image.Height;int Width = this.pbshowbox.Image.Width;Bitmap bitmap = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);Bitmap MyBitmap = (Bitmap)this.pbshowbox.Image;BitmapData oldData = MyBitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);BitmapData newData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);unsafe{byte* pin = (byte*)(oldData.Scan0.ToPointer());byte* pout = (byte*)(newData.Scan0.ToPointer());for (int y = 0; y < oldData.Height; y++){for (int x = 0; x < oldData.Width; x++){pout[0] = (byte)(255 - pin[0]);pout[1] = (byte)(255 - pin[1]);pout[2] = (byte)(255 - pin[2]);pin = pin + 3;pout = pout + 3;}pin += oldData.Stride - oldData.Width * 3;pout += newData.Stride - newData.Width * 3;}bitmap.UnlockBits(newData);MyBitmap.UnlockBits(oldData);this.pbshowbox.Image = bitmap;}}else{MessageBox.Show("请先打开一张图片!");}}

六、积木

低像素置0,高像素置255。

        /// <summary>/// 积木实现方法/// </summary>private void Image_Block(){if (this.pbshowbox.Image != null){int Height = this.pbshowbox.Image.Height;int Width = this.pbshowbox.Image.Width;Bitmap bitmap = new Bitmap(Width, Height);Bitmap Mybitmap = (Bitmap)this.pbshowbox.Image;BitmapData oldData = Mybitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);BitmapData newData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);unsafe{byte* pin = (byte*)(oldData.Scan0.ToPointer());byte* pout = (byte*)(newData.Scan0.ToPointer());for (int y = 0; y < oldData.Height; y++){for (int x = 0; x < oldData.Width; x++){int avg = (pin[0] + pin[1] + pin[2]) / 3;if (avg > 128){pout[0] = 255;pout[1] = 255;pout[2] = 255;}else{pout[0] = 0;pout[1] = 0;pout[2] = 0;}pin = pin + 3;pout = pout + 3;}pin = pin + oldData.Stride - oldData.Width * 3;pout = pout + newData.Stride - newData.Width * 3;}bitmap.UnlockBits(newData);Mybitmap.UnlockBits(oldData);this.pbshowbox.Image = bitmap;}}else{MessageBox.Show("请先打开一张图片!");}}

有些图片效果看起来不明显是因为笔者把图缩小了,其实效果挺明显的- -。

 

转载于:https://www.cnblogs.com/zjc0202/p/4398605.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/291538.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql分组查询和子查询语句_6.MySQL分组聚合查询,子查询

自己的MySQL阅读笔记&#xff0c;持续更新&#xff0c;直到看书结束。数据库技术可以有效帮助一个组织或者企业科学、有效的管理数据&#xff0c;也是现在很多企业招聘数据分析师的必备要求之一。大家如果看过MySQL的书&#xff0c;也可以看我的知识导图做一个复习&#xff0c;…

swf 文件在线播放的,怎么能够下载呢?(除视频外其它都可)

点击播放SWF文件的网页上方工具的Internet选项&#xff0c;点击设置&#xff0c;再点击查看文件&#xff0c;里面有播放的SWF文件图标&#xff0c;把它复制就可以了。转载于:https://blog.51cto.com/wangheyu1/1894807

ABP vNext微服务架构详细教程——分布式权限框架(下)

3公共组件添加公共类库Demo.Permissions&#xff0c;编辑Demo.Permissions.csproj文件&#xff0c;将 <Project Sdk"Microsoft.NET.Sdk"> 改为&#xff1a;<Project Sdk"Microsoft.NET.Sdk.Web">为Demo.Permissions项目添加Nuget引用Volo.Abp.…

ios开发第一步--虚拟机安装MAC OS X

暂时还没买Macbook&#xff0c;先用虚拟机练练手。 先说说准备工作&#xff0c;我是在win8下安装的&#xff0c;这个不是关键的&#xff0c;只要Vmware版本和MAC OS X版本确定就行了&#xff0c;win7下同样可以。 1、虚拟机Vmware10.0.0 下载地址 http://pan.baidu.com/s/1jGv…

算法学习笔记(三)-----各种基础排序问题

2019独角兽企业重金招聘Python工程师标准>>> 一、直接插入排序&#xff1a;是最简单的排序方法&#xff0c;算法简单来说就是可以把第一个数a[0]看做有序数组&#xff0c;那么a[1]要插入进来&#xff0c;对比&#xff0c;插入合适位置&#xff1b;然后a[0],a[1]是有…

mac之把打开终端设置快捷键为Ctrl+Alt+T

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程 1、在Automator.app中创建一个AppleScript Finder&#xff0d;>应用程序->Automator打开Automator.app&#xff0c;打开Automator后…

基础磁盘管理

一、设备文件Linux中设备类型分为字符设备与块设备&#xff0c;他们特点分别为&#xff1a;块设备特性&#xff1a;以“块”为单位进行存取&#xff0c;随机访问&#xff0c;例如磁盘字符设备特性&#xff1a;以“字节”单位进行存取&#xff0c;线性访问&#xff0c;例如键盘设…

redhat yum 安装 mysql_Redhat 7 下Mysql8.0.19安装配置图文详解(配合使用 centos YUM源)...

MySQL Database Service数据库服务器具有以下特点&#xff1a; 具有分析引擎的MySQL数据库服务&#xff1a; MySQL数据库服务是一项完全托管的数据库服务&#xff0c;可使用世界上最受欢迎的开源数据库来部署云原生应用程序。MySQL Analytics Engine将性能提高了400倍。 MySQL企…

Elasticsearch数据库

什么是ElasticsearchElasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口。Elasticsearch是用Java语言开发的&#xff0c;并作为Apache许可条款下的开放源码发布&#xff0c;是一种流行的企业级搜索引擎。…

mac之自己摸索的常用快捷键总结

开终端设置快捷键为&#xff1a; CtrlAltT why click here http://blog.csdn.net/u011068702/article/details/63685920 页面最大化&#xff1a; Ctrl Command F 页面最大化后缩小为中等页面&#xff1a; Ctrl Command F 页面最小化&#xff1a; Command M 恢复最…

HTML5 Canvas 画纸飞机组件

纸飞机模拟一个物体在规定设计轴线偏离方位。 1 //三角形2 function DrawTriangle(canvas, A, B, C) {3 //画个三角形,“A、B、C”是顶点4 with (canvas) {5 moveTo(A[0], A[1]);6 lineTo(B[0], B[1]);7 lineTo(C[0], C[1]);8 lineTo(…

[tools]notepad++当前文件路径不是工作路径

Time:2015/04/09 描述&#xff1a; 在notepad中运行lua&#xff0c;工作路径不是当前文件的路径&#xff0c;而是notepad的安装目录 修改&#xff1a; 把差将中的NppExec --> Follow $(CURRENT_DIRECTORY)勾上即可 参考&#xff1a; [1]http://bbs.chinaunix.net/thread-407…

OPPO R9凭创新赢得2000万销量,成2016年热销手机

2016年的手机市场虽然新闻不断但是整体状况并没有以往那么好&#xff0c;各方数据显示&#xff0c;2016年全年全球智能型手机出货量仅有2.3%的微幅增长&#xff0c;虽然中国市场的全年出货量通同比增长6%&#xff0c;但是比往年也大有不如&#xff0c;手机市场已从增量市场进入…

windows7 nginx php mysql_windows7配置Nginx+php+mysql的详细教程

最近在学习php&#xff0c;想把自己的学习经历记录下来&#xff0c;并写一些经验&#xff0c;仅供参考交流。此文适合那些刚刚接触php&#xff0c;想要学习并想要自己搭建Nginxphpmysql环境的同学。当然&#xff0c;你也可以选择集成好的安装包&#xff0c;比如 wamp等&#xf…

基于C#的计时管理器

问题我们使用各种系统时候会遇到以下问题&#xff1a;12306上购买火车票如果15分钟内未完成支付则订单自动取消。会议场馆预定座位&#xff0c;如果10分钟内未完成支付则预定自动取消。在指定时间之后&#xff0c;我需要执行一项任务。我之前做的很多系统&#xff0c;往往都是定…

C语言之malloc和free总结

1、内存分配和函数介绍 内存分配:指在程序执行的过程空间中或者回收存储空间 ,内存分配分为静态内存分配和动态内存分配 ,要实现动态内存分配,就需要有执行这个操作的对象。C语言提供的两个标准库函数:malloc和free。 1)malloc函数 原型:void *malloc(size_t size)…

哈希表(hashtable)的javascript简单实现

javascript中没有像c#,java那样的哈希表(hashtable)的实现。在js中,object属性的实现就是hash表,因此只要在object上封装点方法,简单的使用obejct管理属性的方法就可以实现简单高效的hashtable。 首先简单的介绍关于属性的一些方法&#xff1a; 属性的枚举: for/in循环是遍历对…

HDU 2516 (Fabonacci Nim) 取石子游戏

这道题的结论就是&#xff0c;石子的个数为斐波那契数列某一项的时候&#xff0c;先手必败&#xff1b;否则&#xff0c;先手必胜。 结论很简单&#xff0c;但是证明却不是特别容易。找了好几篇博客&#xff0c;发现不一样的也就两篇&#xff0c;但是这两篇给的证明感觉证得不清…

access的ole对象换成mysql_ACCESS的Ole对象读取写入

Ole对象在Access中存储为二进制文件&#xff0c;读取的时候需要注意转换出的文件的编码格式1OleDbConnection OleConnnewOleDbConnection();2OleConn.ConnectionString"ProviderMicrosoft.Jet.OleDb.4.0;data sourceD:\WorkStation\Dialy_Sol\Dialy\Dialy.mdb";3OleD…

C++之delete常见错误总结

1、动态分配内存后释放了一次,再次释放 1)直接删除2次 int main() {int *a = new int(50);cout<<*a<<endl;delete a;delete a;return 0; } 2)另外一个指针指向分配的内存,然后把这个2个指针都删除 int* p1 = new int(50); int* p2 = p1; //p2和p1 现在指向同一…