⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 轧板标号检测演示dlg.cpp

📁 This file (the project file) contains information at the project level and is used to build a sing
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// 轧板标号检测演示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 + -