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;
}
}
}