1.灰度化、二值化
2.区域生长分割
有一点点问题
用生长因子法
按照一定的生长顺序生长
a.如果是255(亮点),周围没有生长过的有亮点的话,重新生长一个区域
b.如果是255(亮点),周围生长过的有亮点的话,和它保持一致
c.如果是255(亮点),周围生长过的有亮点的话,但不止一个而且不相同,取最小的,
并把连通的相应区域也置为相同的
d.如果是0(暗点) ,无操作
按区域顺序排
// Bmp.cpp: implementation of the CBmp class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Probmp.h"
#include "Bmp.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBmp::CBmp()
{
pBmpBuf = NULL;
}
CBmp::~CBmp()
{
if (pBmpBuf != NULL)
{
free(pBmpBuf);
}
}
bool CBmp::readFromFile(char *fname)
{
/*二进制读方式打开指定的图像文件*/
FILE *fp=fopen(fname,"rb");
if(fp==0) return 0;
/*跳过位图文件头结构BITMAPFILEHEADER*/
fseek(fp, sizeof(BITMAPFILEHEADER),0);
/*定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中*/
BITMAPINFOHEADER head;
fread(&head, sizeof(BITMAPINFOHEADER), 1,fp);
/*获取图像宽、高、每像素所占位数等信息*/
iWidth = head.biWidth;
iHeight = head.biHeight;
iBitCount = head.biBitCount;
/*定义变量,计算图像每行像素所占的字节数(必须是4的倍数)*/
iLineByte = (iWidth * iBitCount/8+3)/4*4;
/*灰度图像有颜色表,且颜色表表项为256*/
RGBQUAD* pColorTable;
if(iBitCount==8) //申请颜色表所需要的空间,读颜色表进内存
{
return false;
}
/*申请位图数据所需要的空间,读位图数据进内存*/
pBmpBuf=new unsigned char[iLineByte * iHeight];
fread(pBmpBuf,1,iLineByte * iHeight,fp);
/*关闭文件*/
fclose(fp);
return true;
}
void CBmp::showInfo()
{
}
/*
void showMsg(char *msg)
{
char str[64]={0};
sprintf(str,"width=%d,height=%d",pBmp->iWidth,pBmp->iHeight);
AfxMessageBox(str);
}
*/
bool CBmp::saveFile(char *fname)
{
return saveBuf2File(fname,iWidth,iHeight,pBmpBuf,iBitCount);
}
bool CBmp::saveBuf2File(char *fname,int width,int height ,unsigned char* pbuf,int bitcount)
{
if(!pbuf)
return false;
if(iBitCount == 8)
return false;
FILE *fp=fopen(fname,"wb");
if(fp==0)
return 0;
BITMAPFILEHEADER fileHead;
fileHead.bfType = 0x4D42;//bmp类型
//bfSize是图像文件4个组成部分之和
int linebyte = (width * bitcount/8+3)/4*4;
fileHead.bfSize= sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
+ linebyte*height;
fileHead.bfReserved1 = 0;
fileHead.bfReserved2 = 0;
//bfOffBits是图像文件前3个部分所需空间之和
fileHead.bfOffBits=54;
//写文件头进文件
fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp);
//申请位图信息头结构变量,填写信息头信息
BITMAPINFOHEADER head;
head.biBitCount=bitcount;
head.biClrImportant=0;
head.biClrUsed=0;
head.biCompression=0;
head.biHeight=height;
head.biPlanes=1;
head.biSize=40;
head.biSizeImage=linebyte*height;
head.biWidth=width;
head.biXPelsPerMeter=0;
head.biYPelsPerMeter=0;
//写位图信息头进内存
fwrite(&head, sizeof(BITMAPINFOHEADER),1, fp);
//写位图数据进文件
fwrite(pBmpBuf, height*linebyte, 1, fp);
//关闭文件
fclose(fp);
return true;
}
void CBmp::toGray()
{
int i,j,k;
unsigned char gray = 0;
for ( i=0 ; i<iWidth ; i++)
{
for ( j=0; j<iHeight ; j++)
{
gray = (*(pBmpBuf+j*iLineByte+i*3)*0.11+
*(pBmpBuf+j*iLineByte+i*3+1)*0.59+*(pBmpBuf+j*iLineByte+i*3+2)*0.3)/3 ;
if (gray > 255)
{
gray = 255;
}
for( k=0; k<3;k++)
*(pBmpBuf+j*iLineByte+i*3+k) = gray;
}
}
}
/*同时要反转*/
void CBmp::to2Value()
{
int i,j,k;
unsigned char gray = 0;
for ( i=0 ; i<iWidth ; i++)
{
for ( j=0; j<iHeight ; j++)
{
if (i==0||j==0||i==iWidth-1||j==iHeight-1)
{
for( k=0; k<3;k++)
*(pBmpBuf+j*iLineByte+i*3+k) = 255;
}
gray = (*(pBmpBuf+j*iLineByte+i*3)+
*(pBmpBuf+j*iLineByte+i*3+1)+*(pBmpBuf+j*iLineByte+i*3+2))/3 ;
if (gray > 70)
{
for( k=0; k<3;k++)
*(pBmpBuf+j*iLineByte+i*3+k) = 0;
}
else
{
for( k=0; k<3;k++)
*(pBmpBuf+j*iLineByte+i*3+k) = 255;
}
}
}
}
bool CBmp::save01File(char* fname)
{
FILE *out;
if((out=fopen(fname,"w"))==NULL)
{
printf("Cant open infile \n");
return false;
}
char *line = (char*)malloc(512*sizeof(char));
memset(line,0,512*sizeof(char));
int i,j;
for ( j=iHeight-1; j>=0 ; j--)
{
for ( i=0 ; i<iWidth ; i++)
{
if (*(pBmpBuf+j*iLineByte+i*3) > 0 )
strcat(line," 1");
else
strcat(line," ");
//strcat(line," 0");
}
strcat(line,"\n");
fputs(line,out);
memset(line,0,512*sizeof(char));
}
free(line);
fclose(out);
}
void replaceValue(unsigned char* mvalpic,int width,int curheight,int yval,int rval)
{
int i,j;
for ( j=1; j<curheight ; j++)
{
for ( i=1 ; i<width-1 ; i++)
{
if (*(mvalpic+j*width+i) == yval)
{
*(mvalpic+j*width+i) = rval;
}
}
}
}
#define Growb1b2() if (val!=0) \
{ if (b1 == 0) \
{\
b1 = val;\
}\
if (b1 !=0 && val!= b1 )\
{\
b2 = val;\
} }
/* 仅对二值图适用*/
bool CBmp::cut()
{
int i,j;
unsigned char value = 0;
unsigned char* valpic = new unsigned char[iWidth*iHeight];
memset(valpic,0,iWidth*iHeight*sizeof(unsigned char));
for ( i=0 ; i<iWidth ; i++)
{
for ( j=0; j<iHeight ; j++)
{
*(valpic+j*iWidth+i) = *(pBmpBuf+j*iLineByte+i*3);
}
}
unsigned char curval = 0;
unsigned char area[20] = {0};
area[curval] = 1;
/* 简单不考虑边缘的*/
/* 第一步迭代 全部分离为类*/
for ( j=1; j<iHeight-1 ; j++)
{
for ( i=1 ; i<iWidth-1 ; i++)
{
/*区域生长*/
if(*(valpic+j*iWidth+i) == 255)
{
if (*(valpic+(j-1)*iWidth+i-1)==0&&
*(valpic+(j-1)*iWidth+i)==0&&
*(valpic+(j-1)*iWidth+i+1)==0&&
*(valpic+(j)*iWidth+i-1)==0)
{
curval++;
area[curval] = 1;
*(valpic+j*iWidth+i) = curval;
}
else
{
unsigned char b1,b2,b3,val;
b1=b2=b3=val=0;
val = *(valpic+(j-1)*iWidth+i-1);
Growb1b2();
val = *(valpic+(j-1)*iWidth+i);
Growb1b2();
val = *(valpic+(j-1)*iWidth+i+1);
Growb1b2();
val = *(valpic+(j)*iWidth+i-1);
Growb1b2();
if (b2 == 0)
{
*(valpic+j*iWidth+i) = b1;
}
else
{
if (b1 <= b2)
{
*(valpic+j*iWidth+i) = b1;
replaceValue(valpic,iWidth,j,b2,b1);
area[b2] = 0;
}
else
{
*(valpic+j*iWidth+i) = b2;
replaceValue(valpic,iWidth,j,b1,b2);
area[b1] = 0;
}
}
}
//扫过的没有255的
}
}
}
/*区域按顺序*/
int m = 1;
int duiying =1;
for (;m<20;m++)
{
if (area[m]==1)
{
if (duiying != m)
{
replaceValue(valpic,iWidth,iHeight,m,duiying);
}
duiying++;
}
}
/*区域1截图*/
int left,right,top,bottom;
left = iWidth;
right = 0;
top = iHeight;
bottom = 0;
for ( j=1; j<iHeight-1 ; j++)
{
for ( i=1 ; i<iWidth-1 ; i++)
{
if (*(valpic+j*iWidth+i) == 1)
{
if (i<left)
{
left = i;
}
if (i>right)
{
right = i;
}
if (j<top)
{
top = j;
}
if (j>bottom)
{
bottom = j;
}
}
}
}
//////////////////////
/* 有问题*/
int b1width = right -left;
int b1height = bottom - top;
int b1bitcount = 24;
int b1linebytes= (b1width * b1bitcount/8+3)/4*4;
unsigned char* pb1buf = (unsigned char* )malloc(b1height*b1linebytes*sizeof(char));
memset(pb1buf,0,b1height*b1linebytes*sizeof(char));
int x,y,k;
for (y=0;y<b1height;y++)
{
for (x=0;x<b1width;x++)
{
for (k=0;k<3;k++)
{
*(pb1buf+y*b1linebytes+x*3+k)=*(pBmpBuf+(j+top)*iLineByte+(i+left)*3);
}
}
}
////////////////////////////////////
saveBuf2File("D://code1.bmp",b1width,b1height ,pb1buf,b1bitcount);
//////////////////////////////////////////////////////////////////////////
/*显示用*/
FILE *out;
if((out=fopen("D://cut.txt","w"))==NULL)
{
printf("Cant open infile \n");
return false;
}
char *line = (char*)malloc(512*sizeof(char));
memset(line,0,512*sizeof(char));
for ( j=iHeight-1; j>=0 ; j--)
{
for ( i=0 ; i<iWidth ; i++)
{
if (*(valpic+j*iWidth+i) > 0 )
{
char str[3]={0};
sprintf(str,"%d",*(valpic+j*iWidth+i));
strcat(line," ");
strcat(line,str);
}
// strcat(line," 1");
else
strcat(line," ");
//strcat(line," 0");
}
strcat(line,"\n");
fputs(line,out);
memset(line,0,512*sizeof(char));
}
free(line);
fclose(out);
/**/
}
// Bmp.h: interface for the CBmp class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_BMP_H__462532D8_96C7_46B9_A453_A3C3CFA04637__INCLUDED_)
#define AFX_BMP_H__462532D8_96C7_46B9_A453_A3C3CFA04637__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
class CBmp
{
public:
void toGray();
void to2Value();
bool cut();
bool saveFile(char* fname);
void showInfo();
bool readFromFile(char* fname);
bool saveBuf2File(char *fname,int width,int height ,unsigned char* pbuf,int bitcount);
bool save01File(char* fname);
int iHeight;
int iWidth;
int iBitCount;
int iLineByte;
unsigned char* pBmpBuf;
CBmp();
virtual ~CBmp();
};
#endif // !defined(AFX_BMP_H__462532D8_96C7_46B9_A453_A3C3CFA04637__INCLUDED_)
void CProbmpDlg::OnButtonOpen()
{
//readBmp("D://check.bmp");
char str[64]={0};
CBmp* pBmp = new CBmp();
pBmp->readFromFile("D://check.bmp");
pBmp->toGray();
pBmp->to2Value();
pBmp->cut();
pBmp->saveFile("D://checkgray.bmp");
//pBmp->save01File("D://check01.txt");
sprintf(str,"width=%d,height=%d",pBmp->iWidth,pBmp->iHeight);
AfxMessageBox(str);
}