灰度直方图统计
有时我们需要知道一幅图中的灰度分布情况,这时就可以采用灰度直方图(histogram)来
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示,图中的横坐标表示灰度值,纵坐标表示该灰度值出现的次数(频率)。图5.16为图5.13的灰度直方图,低灰度的象素占了绝大部分。
图5.16 图5.13的灰度直方图
下面的程序显示一幅图的灰度直方图。有两段程序,第一段统计出每个灰度的象素个数,存放在数组GrayTable[]中,然后产生一个新的窗口,把统计结果显示出来。第二段程序就是该窗口的消息处理函数。要注意的是,由于各灰度出现的频率可能相差很大,所以如何将结果显示在有限的窗口范围内,是一个必须考虑的问题。我们这里的做法是,在所有出现的灰度中,统计出一个最大值max和一个最小值min,假设能显示的窗口最大坐标为270,最小坐标为5,按成比例显示,这样,灰度出现的次数和显示坐标之间呈线形关系。设 a×grayhits+b=coordinate,其中grayhits为灰度出现的次数,coordinate为显示坐标,a和b为两个常数。我们将max和min代入,应该满足a×max+b=270,a×min+b=5;由此可以解得a=265/(max-min),b=270.0-a× max 。
还有一点,不要忘了在WinMain函数中注册那个新产生窗口的窗口类。 int GrayTable[256];
int MaxGrayNum;
int MinGrayNum;
BOOL Histogram(HWND hWnd)
{
D
word
word文档格式规范word作业纸小票打印word模板word简历模板免费word简历
OffBits,BufSize; LPBITMAPINFOHEADER lpImgData;
LPSTR lpPtr;
int x,y;
int grayindex;
HWND hPopupWnd;
int temp;
//计数器清零
for(grayindex=0;grayindex<256;grayindex++)
GrayTable[grayindex]=0;
//OffBits为到实际位图数据的偏移值
OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER); //BufSize为缓冲区的大小
BufSize=OffBits+bi.biHeight*LineBytes; lpImgData=(LPBITMAPINFOHEADER)Global
Lock(hImgData);
for(y=0;y
MaxGrayNum)
MaxGrayNum=temp; //找到更大的了
if( (temp0) )
MinGrayNum=temp; //找 到更小的了
}
GlobalUnlock(hImgData);
//产生新的窗口显示结果
hPopupWnd = CreateWindow ("PopupWindowClass", "Histogram Statistic Window",
WS_OVERLAPPEDWINDOW,50,80,550,350,
hWnd,NULL,ghInst,NULL);
if (hPopupWnd){
ShowWindow (hPopupWnd, SW_SHOW);
UpdateWindow (hPopupWnd);
}
return TRUE;
}
下面是新窗口的消息处理函数。
long FAR PASCAL PopupWndProc (HWND hWnd,UINT message,
WPARAM wParam,LPARAM lParam)
{
HDC hdc; PAINTSTRUCT ps;
DWORD i;
int xstart;
static LOGPEN blp={PS_SOLID,1,1,RGB(0,0,255)}; //蓝色画笔
HPEN bhp; //画笔句柄
float a,b,temp;
char str[10];
//计算上面所说的a,b的值
a=(float)(265.0 /( MaxGrayNum - MinGrayNum) );
b=(float) (270.0-a* MaxGrayNum);
switch (message){
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
bhp = CreatePenIndirect(&blp);
SelectObject(hdc,bhp);
MoveToEx(hdc,2,270,NULL);
LineTo(hdc,518,270); //先画一条水平线
xstart=2;
for(i=0;i<256;i++){
MoveToEx(hdc,xstart,270,NULL);
if (GrayTable[i]!=0)
temp=(float)(a*GrayTable[i]+b);
else temp=0.0f; //如果灰度出现的次数是零,则不画线
LineTo(hdc,xstart,270-(int)temp); //画出该灰度的计数值
if (i%16 ==0){ //画出标尺,每16个一格
MoveToEx(hdc,xstart,270,NULL);
LineTo(hdc,xstart,280);
_itoa(i,str,10);
TextOut(hdc,xstart,285,str,strlen(str));
}
xstart+=2;
}
MoveToEx(hdc,xstart,270,NULL);
LineTo(hdc,xstart,280);
TextOut(hdc,xstart,285,"256",strlen("256"));
EndPaint(hWnd,&ps);
DeleteObject(bhp);
break;
default:
break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}