“所有致我于死地的,也激发我胆魄”,姚贝娜的《心火》,是我近年来听过最好的歌,特此推荐一下。

图像处理,大概分三步:1.LockBits();2.进行处理;3.UnlockBits();这比起 C++ 来,不知清爽几许?

编程,是为了满足人的需求,所以进行灰度处理时,不是简单的 (r + g + b) / 3,而是分别乘以合适的比例值,r * 0.30 + g * 0.59 + b * 0.11。这是因为人眼对 green 最敏感,red 次之,blue 最低。

只实现了灰度处理,边缘提取,二值化,缩小,Rotate 等有限功能,代码不言自明,无需多说。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text; namespace x01.Utilities
{
public static class BitmapHelper
{
/// <summary>
/// 对 bitmap 进行灰度处理。r,g,b 权重相加为 1。
/// </summary>
/// <param name="bmp">所要处理的 bitmap 对象。</param>
/// <param name="rWeight">red 权重。</param>
/// <param name="gWeight">green 权重。</param>
/// <param name="bWeight">blue 权重。</param>
public static void Gray(Bitmap bmp, float rWeight = 0.30f, float gWeight = 0.59f, float bWeight = 0.11f)
{
BitmapData data = bmp.LockBits(new Rectangle(new Point(), bmp.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] buf = new byte[data.Stride * bmp.Height];
Marshal.Copy(data.Scan0, buf, , buf.Length);
for (int y = ; y < bmp.Height * data.Stride; y += data.Stride)
{
for (int x = ; x < bmp.Width * ; x += )
{
int i = y + x;
byte b = buf[i];
byte g = buf[i + ];
byte r = buf[i + ];
buf[i] = buf[i + ] = buf[i + ] = (byte)(b * bWeight + g * gWeight + r * rWeight);
}
}
Marshal.Copy(buf, , data.Scan0, buf.Length);
bmp.UnlockBits(data);
} /// <summary>
/// 对 bitmap 进行中值滤波处理。
/// </summary>
/// <param name="bmp">所要处理的 bitmap 对象。</param>
public static void MedianFilter(Bitmap bmp)
{
BitmapData data = bmp.LockBits(new Rectangle(new Point(), bmp.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe
{
byte* pBuf = (byte*)data.Scan0.ToPointer();
for (int i = ; i < bmp.Height - ; i++)
{
for (int j = ; j < bmp.Width - ; j++)
{
List<byte>[] list = new List<byte>[];
for (int k = ; k < ; k++)
{
list[k] = new List<byte>();
} for (int y = -; y < ; y++)
{
for (int x = -; x < ; x++)
{
int index = (i + y) * data.Stride + (j + x) * ;
for (int k = ; k < ; k++)
{
list[k].Add(pBuf[index + k]);
}
}
} for (int k = ; k < ; k++)
{
list[k].Sort();
} int indexMedian = i * data.Stride + j * ; for (int k = ; k < ; k++)
{
pBuf[indexMedian + k] = list[k][]; // 4: median value after sort.
list[k].Clear();
} list = null;
}
}
} bmp.UnlockBits(data);
} /// <summary>
/// 获取 bitmap 所选的颜色分量直方图。
/// </summary>
/// <param name="bmp">所要处理的 bitmap 对象</param>
/// <param name="bgrOffset">所选的颜色: blue=0, green=1, red=2</param>
/// <returns>返回 256 * 256 大小的 Bitmap 直方图。</returns>
public static Bitmap Histogram(Bitmap bmp, int bgrOffset = )
{
BitmapData data = bmp.LockBits(new Rectangle(new Point(), bmp.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] buf = new byte[data.Stride * bmp.Height];
Marshal.Copy(data.Scan0, buf, , buf.Length); int[] countColors = new int[];
for (int y = ; y < bmp.Height; y++)
{
for (int x = ; x < bmp.Width; x++)
{
int index = y * data.Stride + x * ;
countColors[buf[index + bgrOffset]]++;
}
} bmp.UnlockBits(data); int maxIndex = ;
for (int i = ; i < ; i++)
{
if (countColors[maxIndex] < countColors[i])
{
maxIndex = i;
}
} Bitmap hist = new Bitmap(, );
Graphics g = Graphics.FromImage(hist);
g.Clear(Color.Wheat);
for (int i = ; i < ; i++)
{
int h = * countColors[i] / countColors[maxIndex];
g.DrawLine(new Pen(Color.FromArgb(i, i, i), 1f), i, , i, - h); // top bottom inverse
} return hist;
} public static void ExtractEdge(Bitmap bmp)
{
BitmapData data = bmp.LockBits(new Rectangle(new Point(), bmp.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] buf = new byte[data.Stride * bmp.Height];
byte[] edge = new byte[data.Stride * bmp.Height];
Marshal.Copy(data.Scan0, buf, , buf.Length); for (int y = ; y < bmp.Height - ; y++)
{
for (int x = ; x < bmp.Width - ; x++)
{
int index = y * data.Stride + x * ;
byte gray = (byte)((buf[index] + buf[index + ] + buf[index + ]) / ); int value = ;
for (int i = -; i < ; i++) // neareat eight point
{
for (int j = -; j < ; j++)
{
if (i == && j == )
{
continue;
} int index2 = (y + i) * data.Stride + (x + i) * ;
byte gray2 = (byte)((buf[index2] + buf[index2 + ] + buf[index2 + ]) / );
value += Math.Abs(gray - gray2);
}
} edge[index] = edge[index + ] = edge[index + ] = (byte)(value >> );
}
} Marshal.Copy(edge, , data.Scan0, edge.Length);
bmp.UnlockBits(data);
} /// <summary>
/// 对图像进行二值化处理。
/// </summary>
/// <param name="bmp">处理的图像。</param>
/// <param name="minValue">最小阀值。</param>
/// <param name="maxValue">最大阀值。</param>
public static void Binary(Bitmap bmp, int minValue, int maxValue)
{
BitmapData data = bmp.LockBits(new Rectangle(new Point(), bmp.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] buf = new byte[data.Stride * bmp.Height];
Marshal.Copy(data.Scan0, buf, , buf.Length); for (int y = ; y < bmp.Height; y++)
{
for (int x = ; x < bmp.Width; x++)
{
int index = y * data.Stride + x * ;
int gray = (buf[index] + buf[index+] +buf[index+])/;
if (gray >= minValue && gray <= maxValue)
{
buf[index] = buf[index + ] = buf[index + ] = ;
}
else
{
buf[index] = buf[index + ] = buf[index + ] = ;
}
}
} Marshal.Copy(buf, , data.Scan0, buf.Length);
bmp.UnlockBits(data);
} /// <summary>
/// 对灰度图像进行对比度增强。
/// </summary>
/// <param name="bmp">灰度图像</param>
/// <param name="srcMin">原灰度下界</param>
/// <param name="srcMax">原灰度上界</param>
/// <param name="destMin">目标灰度下界</param>
/// <param name="destMax">目标灰度上界</param>
public static void Enhance(Bitmap bmp, int srcMin, int srcMax, int destMin, int destMax)
{
BitmapData data = bmp.LockBits(new Rectangle(new Point(), bmp.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] buf = new byte[data.Stride * bmp.Height];
Marshal.Copy(data.Scan0, buf, , buf.Length); for (int y = ; y < bmp.Height; y++)
{
for (int x = ; x < bmp.Width; x++)
{
int index = y * data.Stride + x * ;
int gray = (buf[index] + buf[index + ] + buf[index + ]) / ;
float value = (float)(destMax - destMin) / (srcMax - srcMin) * (gray - srcMin) + destMin;
buf[index] = buf[index + ] = buf[index + ] =
value < byte.MinValue ? byte.MinValue : (value > byte.MaxValue ? byte.MaxValue : (byte)value);
}
} Marshal.Copy(buf, , data.Scan0, buf.Length); bmp.UnlockBits(data);
} public static void Enhance(Bitmap bmp, float n)
{
BitmapData data = bmp.LockBits(new Rectangle(new Point(), bmp.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] buf = new byte[data.Stride * bmp.Height];
Marshal.Copy(data.Scan0, buf, , buf.Length); for (int y = ; y < bmp.Height; y++)
{
for (int x = ; x < bmp.Width; x++)
{
int index = y * data.Stride + x * ;
int gray = (buf[index] + buf[index + ] + buf[index + ]) / ;
float value = gray * n;
buf[index] = buf[index + ] = buf[index + ] =
value < byte.MinValue ? byte.MinValue : (value > byte.MaxValue ? byte.MaxValue : (byte)value);
}
} Marshal.Copy(buf, , data.Scan0, buf.Length);
bmp.UnlockBits(data);
} public static void ConnectRegion(Bitmap bmp)
{
BitmapData data = bmp.LockBits(new Rectangle(new Point(), bmp.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] buf = new byte[data.Stride * bmp.Height];
Marshal.Copy(data.Scan0, buf, , buf.Length); int sign = ;
for (int y = ; y < bmp.Height; y++)
{
for (int x = ; x < bmp.Width; x++)
{
int index = y * data.Stride + x * ;
if (buf[index] == )
{
SignRegion(buf, x * , y * data.Stride, sign, data.Stride, bmp.Width, bmp.Height);
sign += ;
}
}
} Marshal.Copy(buf, , data.Scan0, buf.Length);
bmp.UnlockBits(data);
} public static void SignRegion(byte[] buf, int x, int y, int sign, int stride, int width, int height)
{
int index = x + y;
buf[index] = buf[index + ] = buf[index + ] = (byte)sign; if (x > && buf[index -] == ) // left
{
SignRegion(buf, x - , y, sign, stride, width, height);
} if (x < width * - && buf[index + ] == ) // right
{
SignRegion(buf, x + , y, sign, stride, width, height);
} if (y > && buf[index - stride] == ) // top
{
SignRegion(buf, x, y - stride, sign, stride, width, height);
} if (y < height * stride && buf[index + stride] == ) // bottom
{
SignRegion(buf, x, y + stride, sign, stride, width, height);
} } /// <summary>
/// 缩小图像。
/// </summary>
/// <param name="bmp">图像</param>
/// <param name="widthFactor">宽度缩小倍数</param>
/// <param name="heightFactor">高度缩小倍数</param>
public static void Dilation(Bitmap bmp, float widthFactor, float heightFactor)
{
BitmapData data = bmp.LockBits(new Rectangle(new Point(), bmp.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] buf = new byte[data.Stride * bmp.Height];
Marshal.Copy(data.Scan0, buf, , buf.Length); byte[] result = new byte[data.Stride * bmp.Height];
for (int y = ; y < bmp.Height; y++)
{
for (int x = ; x < bmp.Width; x++)
{
int index = y * data.Stride + x * ; int rx = (int)(x * widthFactor);
int ry = (int)(y * heightFactor);
if (rx < || rx >= bmp.Width || ry < || ry >= bmp.Height)
{
continue;
}
int rindex = ry * data.Stride + rx * ; result[index] = buf[rindex];
result[index + ] = buf[rindex + ];
result[index + ] = buf[rindex + ];
}
} Marshal.Copy(result, , data.Scan0, result.Length);
bmp.UnlockBits(data);
} public static void Translate(Bitmap bmp, int xOffset, int yOffset)
{
BitmapData data = bmp.LockBits(new Rectangle(new Point(), bmp.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] buf = new byte[data.Stride * bmp.Height];
Marshal.Copy(data.Scan0, buf, , buf.Length); byte[] result = new byte[data.Stride * bmp.Height];
for (int y = ; y < bmp.Height; y++)
{
for (int x = ; x < bmp.Width; x++)
{
int index = y * data.Stride + x * ; int rx = x - xOffset;
int ry = y - yOffset;
if (rx < || rx >= bmp.Width || ry < || ry >= bmp.Height)
{
continue;
}
int rindex = ry * data.Stride + rx * ; result[index] = buf[rindex];
result[index + ] = buf[rindex + ];
result[index + ] = buf[rindex + ];
}
} Marshal.Copy(result, , data.Scan0, result.Length);
bmp.UnlockBits(data);
} public static void Rotate(Bitmap bmp, float angle, Point center)
{
BitmapData data = bmp.LockBits(new Rectangle(new Point(), bmp.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] buf = new byte[data.Stride * bmp.Height];
Marshal.Copy(data.Scan0, buf, , buf.Length); byte[] result = new byte[data.Stride * bmp.Height];
for (int y = ; y < bmp.Height; y++)
{
for (int x = ; x < bmp.Width; x++)
{
int index = y * data.Stride + x * ; int rx = (int)( (x - center.X) * Math.Cos(angle * Math.PI / )
- (y - center.Y) * Math.Sin(angle * Math.PI / ) + center.X );
int ry = (int)( (x - center.X) * Math.Sin(angle * Math.PI / )
+ (y - center.Y) * Math.Cos(angle * Math.PI / ) + center.Y ); if (rx < || rx >= bmp.Width || ry < || ry >= bmp.Height)
{
continue;
}
int rindex = ry * data.Stride + rx * ; result[index] = buf[rindex];
result[index + ] = buf[rindex + ];
result[index + ] = buf[rindex + ];
}
} Marshal.Copy(result, , data.Scan0, result.Length);
bmp.UnlockBits(data);
}
}
}

BitmapHelper

如果要处理图像,Paint.Net 是款不错的软件。

x01.BitmapHelper:图像处理的更多相关文章

  1. x01.os.12: 在 windows 中写 OS

    在 windows 中写操作系统,需要一系列的辅助工具.在此,要感谢川谷秀实!所有工具,都在 z_tools 文件夹中.有了大师的帮助,不妨也来尝试在 windows 中写一把 OS. 源代码及工具可 ...

  2. Atitit 图像处理和计算机视觉的分类 三部分 图像处理 图像分析 计算机视觉

    Atitit 图像处理和计算机视觉的分类 三部分 图像处理 图像分析 计算机视觉 1.1. 按照当前流行的分类方法,可以分为以下三部分:三部分 图像处理 图像分析 计算机视觉1 1.2. 图像处理需要 ...

  3. Atitit 图像处理的摩西五经attilax总结

    Atitit 图像处理的摩西五经attilax总结 1. 数字图像处理(第三版)1 2. 图像处理基础(第2版)(世界著名计算机教材精选)1 3. 计算机视觉特征提取与图像处理(第三版)2 4. Op ...

  4. Atitit 图像处理的心得与疑惑 attilax总结

    Atitit 图像处理的心得与疑惑 attilax总结 1.1. 使用类库好不好??还是自己实现算法1 1.2. 但是,如果遇到类库体积太大,后者没有合适的算法,那就只能自己开发算法了1 1.3. 如 ...

  5. Atitit 图像处理 调用opencv 通过java  api   attilax总结

    Atitit 图像处理 调用opencv 通过java  api   attilax总结 1.1. Opencv java api的支持 opencv2.4.2 就有了对java api的支持1 1. ...

  6. Atitit MATLAB 图像处理 经典书籍attilax总结

    Atitit MATLAB 图像处理 经典书籍attilax总结 1.1. MATLAB数字图像处理1 1.2. <MATLAB实用教程(第二版)>((美)穆尔 著)[简介_书评_在线阅读 ...

  7. Atitit 图像处理类库大总结attilax qc20

    Atitit 图像处理类库大总结attilax qc20 1.1. 选择与组合不同的图像处理类库1 1.2. Halcon 貌似商业工具,功能强大.1 1.3. Openvc  Openvc功能也是比 ...

  8. Atitit MATLAB 图像处理attilax总结

    Atitit MATLAB 图像处理attilax总结 1.1. 下载 Matlab7.0官方下载_Matlab2012 v7.0 官方简体中文版-办公软件-系统大全.html1 1.2. Matla ...

  9. 使用MATLAB对图像处理的几种方法(下)

     试验报告 一.试验原理: 图像点处理是图像处理系列的基础,主要用于让我们熟悉Matlab图像处理的编程环境.灰度线性变换和灰度拉伸是对像素灰度值的变换操作,直方图是对像素灰度值的统计,直方图均衡是对 ...

随机推荐

  1. 三层架构与MVC之间的区别

    文章转发自:http://www.admin10000.com/document/535.html 我们平时总是将三层架构与MVC混为一谈,殊不知它俩并不是一个概念.下面我来为大家揭晓我所知道的一些真 ...

  2. PDF.NET SOD 开源框架红包派送活动 && 新手快速入门指引

    一.框架的由来  快速入门 有关框架的更多信息,请看框架官方主页! 本套框架的思想是借鉴Java平台的Hibernate 和 iBatis 而来,兼有ORM和SQL-MAP的特性,同时还参考了后来.N ...

  3. C#微信公众平台开发者模式开启代码

    using System;using System.IO;using System.Text;using System.Web.Security; namespace HPZJ.Web.sys.exc ...

  4. Spring4学习笔记 - 配置Bean - 自动装配 关系 作用域 引用外部属性文件

    1 Autowire自动装配 1.1 使用:只需在<bean>中使用autowire元素 <bean id="student" class="com.k ...

  5. EasyDropDown – 很棒的下拉菜单,含精美主题

    EasyDropDown 是一个 jQuery 插件,你可以毫不费力地将简陋的 Select 元素设置为可定制风格的下拉菜单,用于表单或者一般的导航.和著名的下拉插件 Chosen 很像,但是具有自己 ...

  6. 【CSS3】css3:box-sizing属性

    本文介绍了css3中的box-sizing属性,在这之前读者需要预备知识width的范围. 浏览器的支持情况 Browser Suppored Notes Internet Explorer Yes ...

  7. react native 学习一(环境搭配和常见错误的解决)

    react native 学习一(环境搭配) 首页,按照http://reactnative.cn/docs/0.30/getting-started.html#content上的介绍,下载安装pyt ...

  8. [deviceone开发]-百度地图do_BaiduMap的示例

    一.简介 这个示例展示了百度地图的基本使用,并增加了一个自定义弹出的标示.这个标示是一个自定义的label,里面是地点的文字描述.因为这个组件需要根据应用app的包名去申请不同的key,所以提供一个可 ...

  9. User Profile Service Application 配置同步连接时,报 MOSS MA not found

    最近在试着配置"我的网站",不知什么原因在配置同步连接时报:MOSS MA not found 搜索发现,需要启动Forefront Identity Manager Servic ...

  10. 如何查找SAP的事务代码清单

    SAP系统中,为了省去输入程序名称等繁琐步骤,SAP提供一种命令,称作‘事务代码’,通过执行事务代码达到快速进入相应程序的目的.那么在系统中如何去查找事务代码,事务代码和程序的对应关系如何呢?我们可以 ...