using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using AForge.Imaging.Filters;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
namespace ImageProcessLearn
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
}
//窗体加载时
private void FormMain_Load(object sender, EventArgs e)
{
//显示原始图像
pbSource.Image = Image.FromFile("wky_tms_2272x1704.jpg");
}
//使用选定的类库处理图像
private void btnProcess_Click(object sender, EventArgs e)
{
if (rbAForge.Checked)
{
ProcessImageWithAforge();
}
else if (rbEmgucv.Checked)
{
ProcessImageWithEmgucv();
}
else if (rbOpencv.Checked)
{
ProcessImageWithOpencv();
}
else if (rbOwnMethod.Checked)
ProcessImageWithOwnMethod();
}
/// <summary>
/// 使用AForge.net处理图像
/// </summary>
private void ProcessImageWithAforge()
{
Stopwatch sw = new Stopwatch(); //计时器
//灰度
sw.Start();
Grayscale grayscaleFilter = new Grayscale(0.299, 0.587, 0.114);
Bitmap bitmapGrayscale = grayscaleFilter.Apply((Bitmap)pbSource.Image);
sw.Stop();
double timeGrayscale = sw.Elapsed.TotalMilliseconds;
if (pbGrayscale.Image != null)
{
pbGrayscale.Image.Dispose();
pbGrayscale.Image = null;
}
pbGrayscale.Image = bitmapGrayscale;
//二值化
sw.Reset();
sw.Start();
Threshold thresholdFilter = new Threshold(128);
Bitmap bitmapThreshold = thresholdFilter.Apply(bitmapGrayscale);
sw.Stop();
double timeThreshold = sw.Elapsed.TotalMilliseconds;
if (pbThreshold.Image != null)
{
pbThreshold.Image.Dispose();
pbThreshold.Image = null;
}
pbThreshold.Image = bitmapThreshold;
//输出所用时间
txtResult.Text += string.Format("类库:AForge.net,灰度:{0:F05}毫秒,二值化:{1:F05}毫秒\r\n", timeGrayscale, timeThreshold);
}
/// <summary>
/// 使用EmguCv处理图像
/// </summary>
private void ProcessImageWithEmgucv()
{
Stopwatch sw = new Stopwatch(); //计时器
//灰度
Image<Bgr, Byte> imageSource = new Image<Bgr, byte>((Bitmap)pbSource.Image);
sw.Start();
Image<Gray, Byte> imageGrayscale = imageSource.Convert<Gray, Byte>();
sw.Stop();
double timeGrayscale = sw.Elapsed.TotalMilliseconds;
if (pbGrayscale.Image != null)
{
pbGrayscale.Image.Dispose();
pbGrayscale.Image = null;
}
pbGrayscale.Image = imageGrayscale.ToBitmap();
//二值化
sw.Reset();
sw.Start();
Image<Gray, Byte> imageThreshold = imageGrayscale.ThresholdBinary(new Gray(128), new Gray(255));
sw.Stop();
double timeThreshold = sw.Elapsed.TotalMilliseconds;
if (pbThreshold.Image != null)
{
pbThreshold.Image.Dispose();
pbThreshold.Image = null;
}
pbThreshold.Image = imageThreshold.ToBitmap();
//输出所用时间
txtResult.Text += string.Format("类库:EmguCv,灰度:{0:F05}毫秒,二值化:{1:F05}毫秒\r\n", timeGrayscale, timeThreshold);
}
/// <summary>
/// 使用Open Cv P/Invoke处理图像
/// </summary>
unsafe private void ProcessImageWithOpencv()
{
Stopwatch sw = new Stopwatch(); //计时器
//灰度
Image<Bgr, Byte> imageSource = new Image<Bgr, byte>((Bitmap)pbSource.Image);
IntPtr ptrSource = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MIplImage)));
Marshal.StructureToPtr(imageSource.MIplImage, ptrSource, true);
sw.Start();
IntPtr ptrGrayscale = CvInvoke.cvCreateImage(imageSource.Size, IPL_DEPTH.IPL_DEPTH_8U, 1);
CvInvoke.cvCvtColor(ptrSource, ptrGrayscale, COLOR_CONVERSION.CV_BGR2GRAY);
sw.Stop();
double timeGrayscale = sw.Elapsed.TotalMilliseconds;
if (pbGrayscale.Image != null)
{
pbGrayscale.Image.Dispose();
pbGrayscale.Image = null;
}
pbGrayscale.Image = ImageConverter.IplImagePointerToBitmap(ptrGrayscale);
//二值化
sw.Reset();
sw.Start();
IntPtr ptrThreshold = CvInvoke.cvCreateImage(imageSource.Size, IPL_DEPTH.IPL_DEPTH_8U, 1);
CvInvoke.cvThreshold(ptrGrayscale, ptrThreshold, 128d, 255d, THRESH.CV_THRESH_BINARY);
sw.Stop();
double timeThreshold = sw.Elapsed.TotalMilliseconds;
if (pbThreshold.Image != null)
{
pbThreshold.Image.Dispose();
pbThreshold.Image = null;
}
pbThreshold.Image = ImageConverter.IplImagePointerToBitmap(ptrThreshold);
//释放资源
//CvInvoke.cvReleaseImage(ref ptrThreshold);
//CvInvoke.cvReleaseImage(ref ptrGrayscale);
Marshal.FreeHGlobal(ptrSource);
//输出所用时间
txtResult.Text += string.Format("类库:OpenCv P/Invoke,灰度:{0:F05}毫秒,二值化:{1:F05}毫秒\r\n", timeGrayscale, timeThreshold);
}
/// <summary>
/// 使用自定义的方法处理图像
/// </summary>
private void ProcessImageWithOwnMethod()
{
Stopwatch sw = new Stopwatch(); //计时器
//灰度
sw.Start();
Bitmap bitmapGrayscale = Grayscale((Bitmap)pbSource.Image);
sw.Stop();
double timeGrayscale = sw.Elapsed.TotalMilliseconds;
if (pbGrayscale.Image != null)
{
pbGrayscale.Image.Dispose();
pbGrayscale.Image = null;
}
pbGrayscale.Image = bitmapGrayscale;
//二值化
sw.Reset();
sw.Start();
Bitmap bitmapThreshold = Threshold(bitmapGrayscale, 128);
sw.Stop();
double timeThreshold = sw.Elapsed.TotalMilliseconds;
if (pbThreshold.Image != null)
{
pbThreshold.Image.Dispose();
pbThreshold.Image = null;
}
pbThreshold.Image = bitmapThreshold;
//输出所用时间
txtResult.Text += string.Format("类库:自定义方法,灰度:{0:F05}毫秒,二值化:{1:F05}毫秒\r\n", timeGrayscale, timeThreshold);
}
/// <summary>
/// 将指定图像转换成灰度图
/// </summary>
/// <param name="bitmapSource">源图像支持3通道或者4通道图像,支持Format24bppRgb、Format32bppRgb和Format32bppArgb这3种像素格式</param>
/// <returns>返回灰度图,如果转化失败,返回null。</returns>
private Bitmap Grayscale(Bitmap bitmapSource)
{
Bitmap bitmapGrayscale = null;
if (bitmapSource != null && (bitmapSource.PixelFormat == PixelFormat.Format24bppRgb || bitmapSource.PixelFormat == PixelFormat.Format32bppArgb || bitmapSource.PixelFormat == PixelFormat.Format32bppRgb))
{
int width = bitmapSource.Width;
int height = bitmapSource.Height;
Rectangle rect = new Rectangle(0, 0, width, height);
bitmapGrayscale = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
//设置调色板
ColorPalette palette = bitmapGrayscale.Palette;
for (int i = 0; i < palette.Entries.Length; i++)
palette.Entries[i] = Color.FromArgb(255, i, i, i);
bitmapGrayscale.Palette = palette;
BitmapData dataSource = bitmapSource.LockBits(rect, ImageLockMode.ReadOnly, bitmapSource.PixelFormat);
BitmapData dataGrayscale = bitmapGrayscale.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
byte b, g, r;
int strideSource = dataSource.Stride;
int strideGrayscale = dataGrayscale.Stride;
unsafe
{
byte* ptrSource = (byte*)dataSource.Scan0.ToPointer();
byte* ptr1;
byte* ptrGrayscale = (byte*)dataGrayscale.Scan0.ToPointer();
byte* ptr2;
if (bitmapSource.PixelFormat == PixelFormat.Format24bppRgb)
{
for (int row = 0; row < height; row++)
{
ptr1 = ptrSource + strideSource * row;
ptr2 = ptrGrayscale + strideGrayscale * row;
for (int col = 0; col < width; col++)
{
b = *ptr1;
ptr1++;
g = *ptr1;
ptr1++;
r = *ptr1;
ptr1++;
*ptr2 = (byte)(0.114 * b + 0.587 * g + 0.299 * r);
ptr2++;
}
}
}
else //bitmapSource.PixelFormat == PixelFormat.Format32bppArgb || bitmapSource.PixelFormat == PixelFormat.Format32bppRgb
{
for (int row = 0; row < height; row++)
{
ptr1 = ptrSource + strideGrayscale * row;
ptr2 = ptrGrayscale + strideGrayscale * row;
for (int col = 0; col < width; col++)
{
b = *ptr1;
ptr1++;
g = *ptr1;
ptr1++;
r = *ptr1;
ptr1 += 2;
*ptr2 = (byte)(0.114 * b + 0.587 * g + 0.299 * r);
ptr2++;
}
}
}
}
bitmapGrayscale.UnlockBits(dataGrayscale);
bitmapSource.UnlockBits(dataSource);
}
return bitmapGrayscale;
}
/// <summary>
/// 将指定的灰度图像转换成二值图像。如果某个像素的值大于等于阀值,该像素置为白色;否则置为黑色。
/// 目前支持8bpp和16bpp两种灰度图像的转换,对于8bpp,阀值介于0~255之间;对于16bpp,阀值介于0~65535之间。
/// </summary>
/// <param name="bitmapGrayscale">灰度图像</param>
/// <param name="thresholdValue">阀值</param>
/// <returns>返回转换之后的二值图像;如果转换失败,返回null。</returns>
private Bitmap Threshold(Bitmap bitmapGrayscale,int thresholdValue)
{
Bitmap bitmapThreshold = null;
if (bitmapGrayscale != null)
{
int width = bitmapGrayscale.Width;
int height = bitmapGrayscale.Height;
Rectangle rect = new Rectangle(0, 0, width, height);
PixelFormat pixelFormat = bitmapGrayscale.PixelFormat;
if (pixelFormat == PixelFormat.Format8bppIndexed)
{
if (thresholdValue >= 0 && thresholdValue <= 255)
{
bitmapThreshold = (Bitmap)bitmapGrayscale.Clone();
byte white = 255;
byte black = 0;
BitmapData data = bitmapThreshold.LockBits(rect, ImageLockMode.ReadWrite, pixelFormat);
unsafe
{
byte* ptrStart = (byte*)data.Scan0.ToPointer();
byte* ptr1;
for (int row = 0; row < height; row++)
{
ptr1 = ptrStart + data.Stride * row;
for (int col = 0; col < width; col++)
{
*ptr1 = (*ptr1 < thresholdValue) ? black : white;
ptr1++;
}
}
}
bitmapThreshold.UnlockBits(data);
}
}
else if (pixelFormat == PixelFormat.Format16bppGrayScale)
{
bitmapThreshold = (Bitmap)bitmapGrayscale.Clone();
UInt16 white = 65535;
UInt16 black = 0;
BitmapData data = bitmapThreshold.LockBits(rect, ImageLockMode.ReadWrite, pixelFormat);
unsafe
{
byte* ptrStart = (byte*)data.Scan0.ToPointer();
UInt16* ptr1;
for (int row = 0; row < height; row++)
{
ptr1 = (UInt16*)(ptrStart + data.Stride * row);
for (int col = 0; col < width; col++)
{
*ptr1 = (*ptr1 < thresholdValue) ? black : white;
ptr1++;
}
}
}
bitmapThreshold.UnlockBits(data);
}
}
return bitmapThreshold;
}
}
}