阿发伯的业余编程心得

导航

图像的灰度与二值化

    图像的灰度化与二值化是图像处理中最常见的处理方法,也是很多图像处理方法的基础,如图像灰度统计、图像识别等。

    图像的灰度化与二值化方法较多,处理过程也比较简单。但切不可因其简单而忽视效率。如常用的图像灰度计算公式: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;

        }
    }
}
//---------------------------------------------------------------------------

    因本文使用的是32位图像数据,所以图像的二值化没有采用通常的赋值操作p->Blue = p->Green = p->Red = 0(或者255),而是采用了位运算。

    下面是使用BCB2007和GDI+图像数据实现图像灰度和二值化的例子代码:

// 锁定GDI+位位图扫描线到data
FORCEINLINE
VOID LockBitmap(Gdiplus::Bitmap *bmp, BitmapData *data)
{
    Gdiplus::Rect r(00, 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, 00);
    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

 

posted on 2011-12-09 10:41  阿发伯  阅读(18862)  评论(4编辑  收藏  举报