📄 轧板标号检测演示dlg.cpp
字号:
// 轧板标号检测演示Dlg.cpp : implementation file
//
#include "stdafx.h"
#include "轧板标号检测演示.h"
#include "轧板标号检测演示Dlg.h"
#include "math.h"
#include "DIAHELP.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMyDlg dialog
CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMyDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CMyDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_lpBit=NULL;
m_lpBitOld=NULL;
}
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMyDlg)
DDX_Control(pDX, IDC_SHOWTEXT, m_result);
DDX_Control(pDX, IDC_EDIT1, m_edit1);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
//{{AFX_MSG_MAP(CMyDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_COMMAND(IDD_OPENFILE, OnOpenfile)
ON_COMMAND(IDD_BINARY, OnBinary)
ON_COMMAND(IDD_PROJECTION, OnProjection)
ON_COMMAND(IDD_PROJECTIONDIVIDE, OnProjectiondivide)
ON_COMMAND(IDD_RECONGNISE, OnRecongnise)
ON_COMMAND(IDD_RELOADFILE, OnReloadfile)
ON_COMMAND(IDD_ONESTEP, OnOnestep)
ON_WM_CTLCOLOR()
ON_WM_MOUSEMOVE()
ON_COMMAND(IDD_ABOUT, OnAbout)
ON_COMMAND(IDD_HELP, OnHelp)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMyDlg message handlers
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
//记录最初的对话框大小
CRect lpRect;
this->GetWindowRect(&lpRect);
WindowMinWidth= lpRect.Width() ;
WindowMinHeight= lpRect.Height();
//装入启动画面
ReadBmpFile("indication.bmp",0);
char directory[200];
::GetCurrentDirectory(200,directory);
IniDir.Format("%s\\",directory);
return TRUE; // return TRUE unless you set the focus to a control
}
void CMyDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CMyDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
if (m_lpBit!=NULL){
BITMAPINFOHEADER bmi;
bmi.biSize=sizeof(BITMAPINFOHEADER);
bmi.biWidth=nWidth;
bmi.biHeight=nHeight;
bmi.biPlanes=1;
bmi.biBitCount=24;//24色
bmi.biCompression=BI_RGB;//不压缩
bmi.biSizeImage=0;//定数值
bmi.biXPelsPerMeter=0;
bmi.biYPelsPerMeter=0;
bmi.biClrUsed=0;
bmi.biClrImportant=0;
CRect lpRect;
this->GetWindowRect(&lpRect);
StretchDIBits(dc.m_hDC,(lpRect.Width()-nWidth)/2,5,nWidth,nHeight,0,0,nWidth,nHeight,
m_lpBit,(BITMAPINFO *)&bmi,DIB_RGB_COLORS,SRCCOPY);
}
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CMyDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CMyDlg::OnOpenfile()
{
int ReturnNum=this->OpenBmpFile(0);
if(ReturnNum==-1)
this->MessageBox("指定的文件不能打开","错误信息",MB_OK);
if(ReturnNum==-2)
this->MessageBox("指定的文件不是位图文件","错误信息",MB_OK);
}
int CMyDlg::OpenBmpFile(int Type)
{
CString StrDefExt=".bmp";//如果文件没有后缀,自动在文件名后添加的后缀,这里可以为NULL
CString StrDefName="*.bmp";//在文件名称中显示的初始数值
CString StrExtFilter="位图文件(*.bmp)|*.bmp||";//在文件类型中显示的初始数值
CFileDialog OpenFileDialog(true,StrDefExt,StrDefName,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
StrExtFilter,NULL);
if((OpenFileDialog.DoModal()==IDOK))
FileName=OpenFileDialog.GetFileName();
else
return 0;
//读取文件数据
int ReturnNum=ReadBmpFile(FileName,0);
if (ReturnNum<1)
return ReturnNum;
this->SetWindow();//窗口布局大小设定
CString capstr;
capstr.Format("打开图像文件 %s",FileName);
m_edit1.SetWindowText(capstr);
m_result.SetWindowText("显示数字");
//激活菜单
menuMain= this->GetMenu();
menuSub= menuMain->GetSubMenu(0) ;
menuSub->EnableMenuItem(IDD_BINARY, MF_ENABLED);
menuSub->EnableMenuItem(IDD_RELOADFILE, MF_ENABLED);
menuSub->EnableMenuItem(IDD_ONESTEP, MF_ENABLED);
this->Invalidate(true);//使窗口失效,从而刷新窗口,显示图片!
return 1;
}
int CMyDlg::ReadBmpFile(CString FileName, int Type)
{
//读取位图文件,返回图形的长、宽、24色像素的指针
CFile BmpFile;
if (!BmpFile.Open(FileName,CFile::modeRead,NULL))
return 0; //读取文件失败
int FileLen=BmpFile.GetLength();
BYTE *lpFile=NULL;
lpFile= new BYTE[FileLen];
//读取文件中全部数据失败
if(!BmpFile.Read (lpFile,FileLen))
{
BmpFile.Close();
return -1;
}
BmpFile.Close();
//文件的头结构指定类型、大小等
BITMAPFILEHEADER *lpBitmapFileHeader;
lpBitmapFileHeader=(BITMAPFILEHEADER *) lpFile;
//从结构中得到文件的大小
int filelength= lpBitmapFileHeader->bfSize ;
//从结构中得到图像数据(不包括调色板数据)在文件中开始地址
int DataOffBits=lpBitmapFileHeader->bfOffBits;
//类型是否为'b'+'m'
if (lpBitmapFileHeader->bfType!='B'+'M'*256) return -2;
BITMAPINFOHEADER *lpBitmapInfoHeader;
//得到BITMAPINFOHEADER(BITMAPINFO) 结构的开始地址
lpBitmapInfoHeader=(BITMAPINFOHEADER *)(lpFile + sizeof(BITMAPFILEHEADER));
//unsigned int PointColorNum=1<<(lpBitmapInfoHeader->biBitCount);
unsigned int PointColorNum=0 ;//图像色彩 真色彩超过12000
switch(lpBitmapInfoHeader->biBitCount)
{ case 1://表示图像单色
PointColorNum=2;break;
case 4://表示图像16色
PointColorNum=16;break;
case 8://表示图像256色
PointColorNum=256;break;
case 24://表示图像真色彩
PointColorNum=1<<(lpBitmapInfoHeader->biBitCount);break;
default:
PointColorNum=1<<(lpBitmapInfoHeader->biBitCount);// 真色彩
}
if(lpBitmapInfoHeader->biCompression!=BI_RGB)
{
::MessageBox(this->m_hWnd,"有压缩数据,代号:" + (char)(lpBitmapInfoHeader->biCompression),"不能显示为图像",MB_OK);
return(0);
}
unsigned int PaletteSize;//得到调色板的大小,可能有压缩
if(lpBitmapInfoHeader->biClrUsed==0)//位图中实际使用的颜色数,因为压缩所以和PointColorNum不同
PaletteSize=PointColorNum;//biClrUsed=0 本位图使用最大的颜色数(biBitCount定)
else
PaletteSize=lpBitmapInfoHeader->biClrUsed;//颜色数从biClrUsed得到
if (lpBitmapInfoHeader->biBitCount >=16)PaletteSize=0;//颜色表有0项目
PaletteSize=PaletteSize*sizeof(RGBQUAD);
//有关数据定义
nWidth=( lpBitmapInfoHeader->biWidth);
nHeight=( lpBitmapInfoHeader->biHeight);
nByteWidth= nWidth*3;//真色彩24位3字节显示一点
if (nByteWidth%4) nByteWidth+=4-(nByteWidth%4);//位图文件每行比需要是4的倍数
m_lpBit = lpFile+DataOffBits;
if (lpBitmapInfoHeader->biBitCount<24)//有调色板显示<16或=16时则转化成24色真色彩
{
RGBQUAD *pPalette=(RGBQUAD *)(lpFile + sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER));
int nLen=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nByteWidth*nHeight;
lpFile=new BYTE[nLen];//改变lpFile的地址使m_lpBit和lpTempBit不重叠
BITMAPFILEHEADER bmh;
BITMAPINFOHEADER bmi;
bmh.bfType='B'+'M'*256;
bmh.bfSize=nLen;
bmh.bfReserved1=0;
bmh.bfReserved2=0;
bmh.bfOffBits=54;//14+40=sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER)
bmi.biSize=sizeof(BITMAPINFOHEADER);//定值 40
bmi.biWidth=nWidth;
bmi.biHeight=nHeight;
bmi.biPlanes=1;//平面数一定为1
bmi.biBitCount=24;//转化为真色彩24位
bmi.biCompression=BI_RGB;//不压缩
bmi.biSizeImage=0;//BI_RGB类型一定为0
bmi.biXPelsPerMeter=0;
bmi.biYPelsPerMeter=0;
bmi.biClrUsed=0;//颜色数
bmi.biClrImportant=0;//所有颜色都是重要色
memset(lpFile,0,nLen);//数据赋值0
memcpy(lpFile,&bmh,sizeof(BITMAPFILEHEADER));
memcpy(lpFile+sizeof(BITMAPFILEHEADER),&bmi,sizeof(BITMAPINFOHEADER));
BYTE *lpTempBit=lpFile+sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER);
int x,y;
unsigned int nBWidth,OldPoint,byteNO,BitNo,Palette,NewPoint;
nBWidth=nWidth;//*lpBitmapInfoHeader->biBitCount;//一行字节代表的像素点数
if (nBWidth%(32/lpBitmapInfoHeader->biBitCount)) //文件中实际应该有的字节大小是4的倍数
nBWidth+=(32/lpBitmapInfoHeader->biBitCount)-(nBWidth%(32/lpBitmapInfoHeader->biBitCount));
for(y=0;y<nHeight;y++)//图像从左下坐标开始
{
for(x=0;x<nWidth;x++)
{
OldPoint=y*nBWidth+x;
switch(lpBitmapInfoHeader->biBitCount)
{case 1://表示图像单色
//if (nBWidth%32) nBWidth+=32-(nBWidth%32);//图像中每行的字节数为4的倍数
//OldPoint=y*nBWidth+x;
byteNO=int(OldPoint / 8);
BitNo=7-(OldPoint % 8);
Palette=m_lpBit[byteNO];
Palette=(Palette>>BitNo) ;
Palette=(Palette & 0X01);
break;
case 4://表示图像16色
//if (nBWidth%8) nBWidth+=8-(nBWidth%8);//图像中每行的字节数为4的倍数
//OldPoint=y*nBWidth+x;
byteNO=int(OldPoint / 2) ;
BitNo=(OldPoint % 2)*4;
Palette=m_lpBit[byteNO];
Palette=((Palette>>BitNo) & 0x0f);
break;
case 8://表示图像256色
//if (nBWidth%4) nBWidth+=4-(nBWidth%4);//图像中每行的字节数为4的倍数
//OldPoint=y*nBWidth+x;
Palette= m_lpBit[OldPoint];
break;
case 16://16位 两字节一点,5bit为一种色彩,blue(低),green(中),red(高),最高5bit无意义
byteNO=OldPoint / 2;
if (!(OldPoint%2))
{
NewPoint=y*nByteWidth+x*3;//24色
BYTE Color[2],GetColor;
Color[0]=m_lpBit[byteNO];
Color[1]=m_lpBit[byteNO+1];
lpTempBit[NewPoint]=(Color[0] & 0x1f) ;
GetColor=((Color[0] >>5) & 0x07) +((Color[1]<<3) & 0x18);
lpTempBit[NewPoint+1]=GetColor ;
GetColor=((Color[1]>>2) & 0x1f);
lpTempBit[NewPoint+2]= GetColor;
}
}
if ((lpBitmapInfoHeader->biBitCount) < 16)
{
if (Palette*4 > PaletteSize) Palette=0;
NewPoint=y*nByteWidth+x*3;//24色
lpTempBit[NewPoint]=(pPalette[Palette].rgbBlue) ;
lpTempBit[NewPoint+1]=(pPalette[Palette].rgbGreen ) ;
lpTempBit[NewPoint+2]=(pPalette[Palette].rgbRed ) ;
}
}
}
}
m_lpBit = lpFile+ sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
m_lpBitOld2 = new BYTE[nByteWidth*nHeight];
memcpy(m_lpBitOld2,m_lpBit,nByteWidth*nHeight);
nOldHeight=nHeight;
return 1;
}
void CMyDlg::OnBinary()
{
//二值化效果
//先是反色处理,因为根据现场的实际输入图字符为白,背景为黑
//算法中需要的是字符为黑,背景为白
//利用了marr边缘算法求取 得到区域,再滤除小面积
//做9×9的Marr算子模板,MArr函数也是一个二阶函数的求导,所以是先用二阶滤波,然后求导
//其中的过零点就是边缘,其实不是过零点,负数的点就是边缘,是一种边缘检测算子
//对于计算结果,还进行了面积滤波
if(m_lpBit==NULL)return;
m_lpBitOld=new BYTE[nByteWidth*nHeight];
memcpy(m_lpBitOld,m_lpBit,nByteWidth*nHeight);
int x,y,i,j;
// #define BASE 4 周家玮修改于8月8日,2006年
const int BASE=4;
// float dr=1.6,temp=0.0;周家玮修改于8月8日,2006年
double dr=1.6,temp=0.0;
// float Marr[9][9]={0.0};周家玮修改于8月8日,2006年
double Marr[9][9]={0.0};
long TotalEdgePoint=0;
long TotalEdgePointGray=0;
long TotalNoEdgePoint=0;
long TotalNoEdgePointGray=0;
float *m_LpTempPoint =new float[nWidth*nHeight];
float *Point= new float[nWidth*nHeight];
if (nByteWidth % 4) nByteWidth+=4-nByteWidth%4;
//反色处理,采用加权平均值法!
for(y=0;y<nHeight;y++)//将3字节的彩色像素像转化成1点灰度显示
{
for(x=0;x<nWidth;x++)
{
int OldPoint=y*nByteWidth+x*3;//得到传入数据中有效部分每点的开始地址
int NewPoint=y*nWidth+x;
Point[NewPoint]=255-(float)(0.299*(float)m_lpBit[OldPoint+2]+0.587*(float)m_lpBit[OldPoint+1]+0.114*(float)m_lpBit[OldPoint]+0.1);
m_LpTempPoint[NewPoint]=255;
//疑问:为什么要定义m_LpTempPoint它呢?有什么用呢?8.19.2006周家玮
}
}
long T1 = ::GetTickCount();//开始时间,以毫秒为单位
//求Marr算子模板
for(x=-BASE;x<=BASE;x++)
{
for(y=-BASE;y<=BASE;y++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -