图像的灰度与二值化
图像的灰度化与二值化是图像处理中最常见的处理方法,也是很多图像处理方法的基础,如图像灰度统计、图像识别等。
图像的灰度化与二值化方法较多,处理过程也比较简单。但切不可因其简单而忽视效率。如常用的图像灰度计算公式:gray = red * 0.299 + green * 0.587 + blue * 0.114,如果在程序代码中直接套用了这个公式,因浮点数的缘故导致代码执行效率较低,如改为定点整数运算,可使执行效率大大提高。
下面是图像的灰度与二值化代码:
// 定义ARGB像素结构
typedef union
{
ARGB Color;
struct
{
BYTE Blue;
BYTE Green;
BYTE Red;
BYTE Alpha;
};
}ARGBQuad, *PARGBQuad;
//---------------------------------------------------------------------------
// 图像数据data灰度化
VOID Gray(BitmapData *data)
{
PARGBQuad p = (PARGBQuad)data->Scan0;
INT offset = data->Stride - data->Width * sizeof(ARGBQuad);
for (UINT y = 0; y < data->Height; y ++, (BYTE*)p += offset)
{
for (UINT x = 0; x < data->Width; x ++, p ++)
p->Blue = p->Green = p->Red =
(UINT)(p->Blue * 29 + p->Green * 150 + p->Red * 77 + 128) >> 8;
}
}
//---------------------------------------------------------------------------
// 图像数据data灰度同时二值化,threshold阀值
VOID GrayAnd2Values(BitmapData *data, BYTE threshold)
{
PARGBQuad p = (PARGBQuad)data->Scan0;
INT offset = data->Stride - data->Width * sizeof(ARGBQuad);
for (UINT y = 0; y < data->Height; y ++, (BYTE*)p += offset)
{
for (UINT x = 0; x < data->Width; x ++, p ++)
{
if (((p->Blue * 29 + p->Green * 150 + p->Red * 77 + 128) >> 8) < threshold)
p->Color &= 0xff000000;
else
p->Color |= 0x00ffffff;
}
}
}
//---------------------------------------------------------------------------
typedef union
{
ARGB Color;
struct
{
BYTE Blue;
BYTE Green;
BYTE Red;
BYTE Alpha;
};
}ARGBQuad, *PARGBQuad;
//---------------------------------------------------------------------------
// 图像数据data灰度化
VOID Gray(BitmapData *data)
{
PARGBQuad p = (PARGBQuad)data->Scan0;
INT offset = data->Stride - data->Width * sizeof(ARGBQuad);
for (UINT y = 0; y < data->Height; y ++, (BYTE*)p += offset)
{
for (UINT x = 0; x < data->Width; x ++, p ++)
p->Blue = p->Green = p->Red =
(UINT)(p->Blue * 29 + p->Green * 150 + p->Red * 77 + 128) >> 8;
}
}
//---------------------------------------------------------------------------
// 图像数据data灰度同时二值化,threshold阀值
VOID GrayAnd2Values(BitmapData *data, BYTE threshold)
{
PARGBQuad p = (PARGBQuad)data->Scan0;
INT offset = data->Stride - data->Width * sizeof(ARGBQuad);
for (UINT y = 0; y < data->Height; y ++, (BYTE*)p += offset)
{
for (UINT x = 0; x < data->Width; x ++, p ++)
{
if (((p->Blue * 29 + p->Green * 150 + p->Red * 77 + 128) >> 8) < threshold)
p->Color &= 0xff000000;
else
p->Color |= 0x00ffffff;
}
}
}
//---------------------------------------------------------------------------
因本文使用的是32位图像数据,所以图像的二值化没有采用通常的赋值操作p->Blue = p->Green = p->Red = 0(或者255),而是采用了位运算。
下面是使用BCB2007和GDI+图像数据实现图像灰度和二值化的例子代码:
// 锁定GDI+位位图扫描线到data
FORCEINLINE
VOID LockBitmap(Gdiplus::Bitmap *bmp, BitmapData *data)
{
Gdiplus::Rect r(0, 0, bmp->GetWidth(), bmp->GetHeight());
bmp->LockBits(&r, ImageLockModeRead | ImageLockModeWrite,
PixelFormat32bppARGB, data);
}
//---------------------------------------------------------------------------
// GDI+位图扫描线解锁
FORCEINLINE
VOID UnlockBitmap(Gdiplus::Bitmap *bmp, BitmapData *data)
{
bmp->UnlockBits(data);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Gdiplus::Bitmap *bmp = new Gdiplus::Bitmap(L"d:\\source1.jpg");
Gdiplus::Graphics *g = new Gdiplus::Graphics(Canvas->Handle);
g->DrawImage(bmp, 0, 0);
BitmapData data;
LockBitmap(bmp, &data);
// Gray(&data);
GrayAnd2Values(&data, 128);
UnlockBitmap(bmp, &data);
g->DrawImage(bmp, data.Width, 0);
delete g;
delete bmp;
}
//---------------------------------------------------------------------------
FORCEINLINE
VOID LockBitmap(Gdiplus::Bitmap *bmp, BitmapData *data)
{
Gdiplus::Rect r(0, 0, bmp->GetWidth(), bmp->GetHeight());
bmp->LockBits(&r, ImageLockModeRead | ImageLockModeWrite,
PixelFormat32bppARGB, data);
}
//---------------------------------------------------------------------------
// GDI+位图扫描线解锁
FORCEINLINE
VOID UnlockBitmap(Gdiplus::Bitmap *bmp, BitmapData *data)
{
bmp->UnlockBits(data);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Gdiplus::Bitmap *bmp = new Gdiplus::Bitmap(L"d:\\source1.jpg");
Gdiplus::Graphics *g = new Gdiplus::Graphics(Canvas->Handle);
g->DrawImage(bmp, 0, 0);
BitmapData data;
LockBitmap(bmp, &data);
// Gray(&data);
GrayAnd2Values(&data, 128);
UnlockBitmap(bmp, &data);
g->DrawImage(bmp, data.Width, 0);
delete g;
delete bmp;
}
//---------------------------------------------------------------------------
如有错误或者建议,请来信指导:maozefa@hotmail.com