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

图像处理,大概分三步: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. struts 用拦截器进行用户权限隔离,未登录用户跳到登录界面 *** 最爱那水货

    一般,我们的web应用都是只有在用户登录之后才允许操作的,也就是说我们不允许非登录认证的用户直接访问某些页面或功能菜单项.对于个别页面来说,可能不需要进行拦截,此时,如果项目采用struts view ...

  2. 性能测试学习之三—— PV->TPS转换模型&TPS波动模型

    PV->TPS转换模型 由上一篇“性能测试学习之二 ——性能测试模型(PV计算模型)“ 得知 TPS = ( (80%*总PV)/(24*60*60*(T/24)))/服务器数量 转换需要注意: ...

  3. The POM for XXX:jar:${com.ld.base.service.version} is missing, no dependency information available

    最近有个jar改了名字后,有个依赖它的工程死活引用的是老名字,导致打包的时候出错,如下所示: [INFO] ---------------------------------------------- ...

  4. HTML5锚点请用id代替name

    HTML5已经去掉name属性,实现锚点时请使用id,实例效果:http://keleyi.com/keleyi/phtml/html5/9.htm 支持Chrome,火狐,IE8以上等浏览器. 以下 ...

  5. 【web前端优化之图片模糊到清晰】看我QQ空间如何显示相片

    前言 此篇文章估计不会太长,有移除首页的风险,但是老夫(称老夫是因为我们真正的叶小钗其实都100多岁啦)是不会怕滴.所以,我来了哟! 题外话:今天我们一起还看了一道前端的面试题,而后我本来还想多找几道 ...

  6. IP查询接口地址

    腾讯的: http://fw.qq.com/ipaddress直接返回本机的IP地址对应的地区 新浪的:http://counter.sina.com.cn/ip?ip=IP地址返回Js数据,感觉不是 ...

  7. iOS 适配iOS9

    1.网络接口不支持https协议,在iOS9下 在iOS9下,系统默认会拦截对http协议接口的访问,因此无法获取http协议接口的数据. 解决方案(以下方法2选1): (1)暂时退回到http协议 ...

  8. C/C++构建系统 -工具汇总

    关于构建系统可以先参考百科 http://en.wikipedia.org/wiki/List_of_build_automation_software http://www.drdobbs.com/ ...

  9. 生成iOSAPP的二维码

    1.打开iTunes,在"应用"里面搜索要找的APP 2.右键要生成二维码的APP,选择"拷贝链接" 3.百度一个二维码生成器 4.把刚才拷贝的链接粘贴进去,点 ...

  10. ios网络编程学习

    //网络访问获取数据//定义一个UIWebView属性,用来展示数据 @property (strong, nonatomic) IBOutlet UIWebView *myWebView; //.. ...