分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
图像的灰度与二值化
http://www.cnblogs.com/maozefa/archive/2011/12/09/2281656.html
图像的灰度化与二值化是图像处理中最常见的处理方法,也是很多图像处理方法的基础,如图像灰度统计、图像识别等。
图像的灰度化与二值化方法较多,处理过程也比较简单。但切不可因其简单而忽视效率。如常用的图像灰度计算公式:gray = red * 0.299 + green * 0.587 + blue * 0.114,如果在程序代码中直接套用了这个公式,因浮点数的缘故导致代码执行效率较低,如改为定点整数运算,可使执行效率大大提高。
下面是图像的灰度与二值化代码:
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+图像数据实现图像灰度和二值化的例子代码:
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;
}
// ---------------------------------------------------------------------------
24位真彩色转换为8位灰度图片(完整代码)
//Code By xets007
//转载请注明出处
//
#include <windows.h>
BOOL BMP24to8(char *szSourceFile,char *szTargetFile);
int main(int argc,char* argv[])
{
//调用这个函数直接把24位真彩色灰度化
BOOL stat=BMP24to8("c://source.bmp","c://target.bmp");
return 0;
}
BOOL BMP24to8(char *szSourceFile,char *szTargetFile)
{
HANDLE hSourceFile=INVALID_HANDLE_VALUE,hTargetFile=INVALID_HANDLE_VALUE;
DWORD dwSourceSize=0,dwTargetSize=0;
PBYTE pSource=NULL,pTarget=NULL;
hSourceFile=CreateFile(szSourceFile,GENERIC_READ,FILE_SHARE_READ,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hSourceFile==INVALID_HANDLE_VALUE)
return FALSE;
dwSourceSize=GetFileSize(hSourceFile,NULL);
pSource=(PBYTE)VirtualAlloc(NULL,dwSourceSize,MEM_COMMIT,PAGE_READWRITE);
//分配空间失败或者文件太小(BMP文件不可能小于54个字节)
if(pSource==NULL||dwSourceSize<=54)
{
CloseHandle(hSourceFile);
return FALSE;
}
DWORD dwTemp=0;
ReadFile(hSourceFile,pSource,dwSourceSize,&dwTemp,NULL);
BITMAPFILEHEADER *pSourceFileHeader=(BITMAPFILEHEADER*)pSource;
BITMAPINFOHEADER *pSourceInfoHeader=(BITMAPINFOHEADER*)(pSource+sizeof(BITMAPFILEHEADER));
//不是BMP文件或者不是24位真彩色
if(pSourceFileHeader->bfType!=0x4d42||pSourceInfoHeader->biBitCount!=24)
{
CloseHandle(hSourceFile);
VirtualFree(pSource,NULL,MEM_RELEASE);
return FALSE;
}
CloseHandle(hSourceFile);
LONG nWidth=pSourceInfoHeader->biWidth;
LONG nHeight=pSourceInfoHeader->b