📄 threshold.c
字号:
// Ex10
// 大津法二值化
#include <windows.h>
#include "image32.h"
#include "stdio.h"
extern HDC hMemDC;
extern struct IMAGE *image;
extern struct IMAGE *Image[10];
void ColorToGray(int m,int n); // 变灰阶
long pg[256],pg1[256];
int T_gray[256],thre_v;
void histog(struct IMAGE *image,long *pg,int Xs, int Ys, int Dx, int Dy)
{ // 统计直方图
BYTE *sc;
int i,j;
sc=(BYTE*) malloc(Dx);
for (i=0;i<256;i++) pg[i]=0;
for(i=0;i<Dy;i++) {
getimage(image,Xs, Ys+i, Dx, 1, sc);
for (j=0;j<Dx;j++) pg[sc[j]]++;
}
free(sc);
}
int Otsu(long *pg,long *pg1) // 大津法取阈值
{
int i,j,p;
double A,B,An,Bn,u,v,qqq[256],max,min;
An=Bn=0;
for (i=0;i<256;i++) {
An+=pg[i]; Bn+=pg[i]*(i+1);
}
for (j=0;j<256;j++) {
A=B=0;
for (i=0;i<=j;i++) {
A+=pg[i]; B+=pg[i]*(i+1);
}
if (A) u=B/A;
else u=0;
if (An-A) v=(Bn-B)/(An-A);
else v=0;
qqq[j]=A*(An-A)*(u-v)*(u-v);
}
max=min=qqq[0]; p=0;
for (i=1;i<256;i++) {
if (qqq[i]>max) {
max=qqq[i];
p=i;
}
else if (qqq[i]<min) min=qqq[i];
}
if (pg1!=0) {
for (i=0;i<256;i++) {
pg1[i]=(long) (120*(qqq[i]-min)/(max-min));
}
}
return(p);
}
void draw_histog(long *pg,int x,int y,int h,int flag)
{ // 绘制直方图
LOGPEN lppen = {PS_SOLID,1,1,RGB(255,0,0)};
DWORD Hist1[256];
int i,j,k,l,t;
HPEN hPen;
hMemDC=CreateMemDC();
for (j=0;j<256;j++) Hist1[j]=pg[j];
k=1;
for (j=0,k=1;j<200;j++) {
for (i=0,t=0;i<256;i++) {
if ((int)(Hist1[i]/k)<h) t++;
}
if (t>252) break;
k++;
}
for (i=0;i<256;i++) {
Hist1[i]/=k;
if ((int) Hist1[i]>h) Hist1[i]=h;
}
lppen.lopnColor=RGB(128,128,128);
hPen=SelectObject(hMemDC,CreatePenIndirect(&lppen));
MoveToEx(hMemDC,x,y,NULL);
LineTo(hMemDC,x+256,y);
DeleteObject(SelectObject(hMemDC,hPen));
lppen.lopnColor=RGB(0,0,0);
hPen=SelectObject(hMemDC,CreatePenIndirect(&lppen));
MoveToEx(hMemDC,x,y-Hist1[0],NULL);
for (i=0;i<256;i++) {
l=Hist1[i];
if (l>0) {
if (flag==0)
MoveToEx(hMemDC,x+i,y,NULL);
LineTo(hMemDC,x+i,y-l);
}
}
DeleteObject(SelectObject(hMemDC,hPen));
DeleteMemDC(hMemDC);
}
void Threshold_G(int *T_gray,int thre)
{ // 灰度变换--两值化
int i,w,b;
thre_v=thre;
b=0; w=255;
for (i=0;i<thre_v;i++) T_gray[i]=b;
for (i=thre_v;i<256;i++) T_gray[i]=w;
}
void GT(struct IMAGE *image,int x,int y,int Dx,int Dy)
{ // 实现灰度变换
BYTE buf[2048];
int i,j;
for (i=0;i<Dy;i++) {
getimage(image,x,y+i,Dx,1,buf);
for (j=0;j<Dx;j++) {
buf[j]=T_gray[buf[j]]; // 查表
}
setimage(image,x,y+i,Dx,1,buf);
}
}
void GT_Threshold(struct IMAGE *image,int x,int y,int Dx,int Dy,int thre)
{ // 灰度变换--两值化
Threshold_G(T_gray,thre);
GT(image,x,y,Dx,Dy);
}
void Threshold(HWND hWnd)
{
int t;
char StringT[20];
if ((Image[0]->hdib==NULL)||(Image[0]->bitcount<8)) return;
ClearDDB();
WriteDDB(Image[0], 0, 0, 0, 0,512,512);
ColorToGray(0,1);
histog(Image[1],pg,0,0,Image[1]->wid,Image[1]->hei);
t=Otsu(pg,pg1);
draw_histog(pg,128,650,125,0);
draw_histog(pg1,640,650,125,1);
hMemDC=CreateMemDC();
MoveToEx(hMemDC,128+t,655,NULL);
LineTo(hMemDC,128+t,670);
MoveToEx(hMemDC,640+t,655,NULL);
LineTo(hMemDC,640+t,670);
TextOut(hMemDC,470,600,"二值化阈值",10);
sprintf(StringT,"%5d",t);
TextOut(hMemDC,490,630,StringT,strlen(StringT));
DeleteMemDC(hMemDC);
GT_Threshold(Image[1],0,0,Image[1]->wid,Image[1]->hei,t);
WriteDDB(Image[1],512, 0, 0, 0,512,512);
InvalidateRect(hWnd,NULL,FALSE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -