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

📄 locateview.cpp

📁 集装箱号码演示程序1.0完美版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// LocateView.cpp : implementation of the CLocateView class
//

#include "stdafx.h"
#include "Locate.h"
#include "LocateDoc.h"
#include "LocateView.h"
#include "MainFrm.h"
#include "DIBAPI.h"
#include "DibAlgo.h"
#include "EdgeContour.h"
#include "DlgHistShow.h"
#include "SetParamtDlg.h"
#include <afxtempl.h>
#include <fstream.h>
#include <math.h>
#include <conio.h>



#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CLocateView

IMPLEMENT_DYNCREATE(CLocateView, CView)

BEGIN_MESSAGE_MAP(CLocateView, CView)
	//{{AFX_MSG_MAP(CLocateView)
	ON_COMMAND(ID_IMAGE_TOGRAY, OnImageToGray)
	ON_COMMAND(ID_GRAY_TOSTRE, OnStretch)
	ON_COMMAND(ID_GRAY_TOTHRE, OnThreshold)
	ON_COMMAND(ID_GRAY_TOTEMP, OnTemplate)
	ON_COMMAND(ID_MEDIAN_TOFILTER, OnMedianFilter)
	ON_COMMAND(ID_IMAGE_TOPROJECT, OnFiltrate)
	ON_COMMAND(ID_TEMP_TOSUBRECT, OnSubrect)
	ON_COMMAND(ID_IMAGE_OPEN, OnImageOpen)
	ON_COMMAND(ID_GRAY_EQUA, OnGrayEqualize)
	ON_COMMAND(ID_VIEW_HIST, OnViewHist)
	ON_COMMAND(ID_IMAGE_SAVE, OnImageSave)
	ON_COMMAND(ID_OPTION_PARAM, OnOptionParam)
	ON_COMMAND(ID_FIRST,OnFirst)
	ON_COMMAND(ID_MIDDLE,OnMiddle)
	ON_COMMAND(ID_LAST,OnLast)
	ON_COMMAND(ID_RESULT,OnResult)
	//}}AFX_MSG_MAP
	// Standard printing commands
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CLocateView construction/destruction

CLocateView::CLocateView()
{
	m_hDIB   = NULL;
	m_palDIB = NULL;

	m_lMaxDist   = 20;	// 最大允许的跳变点间距
	m_lMinDotNum = 10;	// 最小允许的每行跳变点数

	m_nMaxOffset = 100;	// 同一区域两行最左端允许相差的最大距离
	m_nMaxGap    = 4;	// 同一区域最多允许的间断行数
	m_nMinHeight = 20;	// 车牌照的最小高度
	m_nMinWidth  = 100;	// 车牌照的最小宽度
}

CLocateView::~CLocateView()
{
	if (m_hDIB != NULL)
	{
		::GlobalFree((HGLOBAL) m_hDIB);
	}
	
	if (m_palDIB != NULL)	// 判断调色板是否存在
	{
		delete m_palDIB;
	}
}

/////////////////////////////////////////////////////////////////////////////
// CLocateView drawing

void CLocateView::OnDraw(CDC* pDC)
{
	// 显示等待光标
	BeginWaitCursor();

	// 判断DIB是否为空
	if (m_hDIB != NULL)
	{
		LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
		
		// 获取DIB宽度
		int cxDIB = (int) ::DIBWidth(lpDIB);
		
		// 获取DIB高度
		int cyDIB = (int) ::DIBHeight(lpDIB);

		::GlobalUnlock((HGLOBAL) m_hDIB);
		
		CRect rcDIB;
		rcDIB.top = rcDIB.left = 0;
		rcDIB.right = cxDIB;
		rcDIB.bottom = cyDIB;
		
		// 输出DIB
		::PaintDIB(pDC->m_hDC, &rcDIB, m_hDIB ,	&rcDIB, GetViewPalette());
	}
	
	// 恢复正常光标
	EndWaitCursor();
}

/////////////////////////////////////////////////////////////////////////////
// CLocateView diagnostics

#ifdef _DEBUG
void CLocateView::AssertValid() const
{
	CView::AssertValid();
}

void CLocateView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CLocateDoc* CLocateView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CLocateDoc)));
	return (CLocateDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CLocateView message handlers

// 打开车牌照片
void CLocateView::OnImageOpen() 
{
	CString strPhotoPath;	// 照片文件路径

    char fullPath[100]; 
	char dir[100];
    
	CFileDialog dlg(TRUE,NULL,NULL,0,"JPEG 文件 (*.jpg)|*.jpg||",this);

	GetModuleFileName(AfxGetInstanceHandle(), fullPath ,100); 
   _splitpath(fullPath,NULL,dir,NULL,NULL);

    dlg.m_ofn.lpstrInitialDir=dir;

	if (dlg.DoModal() != IDOK)
	{
		return;
	}
	strPhotoPath = dlg.GetPathName();

	// 调用JpgVsBmp.dll中提供的JPG=>BMP的功能
	HINSTANCE hInst = ::LoadLibrary("JpgVSbmp.dll");
	if( hInst == NULL )
	{
		AfxMessageBox("缺少JpgVSbmp.dll文件!");
		return;
	}
	typedef  bool(__stdcall CHANGE)(LPCTSTR,LPCTSTR,int);
	CHANGE* pFunc	= (CHANGE *)::GetProcAddress(hInst,"JpgToBmp");
	pFunc(strPhotoPath, "Temp.bmp", 24);
	::FreeLibrary(hInst);
	
	// 从磁盘载入bmp文件
	CFile file;
	file.Open("Temp.bmp", CFile::modeRead);
	m_hDIB = ::ReadDIBFile(file);
 	if (m_hDIB != NULL)
 	{
 		Invalidate();
 	}

	file.Close();
	CFile::Remove("Temp.bmp");
}

// 保存车牌照片为bmp文件
void CLocateView::OnImageSave() 
{
	CFileDialog dlg(FALSE,NULL,NULL,0,"BMP 文件 (*.bmp)|*.bmp||",this);
	if (dlg.DoModal() != IDOK)
	{
		return;
	}
	CString strBMPPath = dlg.GetPathName();

	CFile file;
	file.Open(strBMPPath, CFile::modeCreate|CFile::modeWrite);
	::SaveDIB(m_hDIB,file);
	file.Close();
}

// 灰度化
void CLocateView::OnImageToGray() 
{
	if (m_hDIB == NULL)
		return;

	Copy();	// 在处理之前先保存原来的图像

	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);	
	ConvertToGrayScale(lpDIB);
	::GlobalUnlock((HGLOBAL) m_hDIB);

	Invalidate();

    CStatusBar* pStatus=(CStatusBar*) 
    AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR); 
    pStatus->SetPaneText(0,"灰度化处理"); 

}

// 直方图均衡化
void CLocateView::OnGrayEqualize() 
{
	if (m_hDIB == NULL)
		return;

	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);	
	LPSTR lpDIBBits = FindDIBBits(lpDIB);
	int lWidth = DIBWidth(lpDIB);
	int lHeight = DIBHeight(lpDIB);
	InteEqualize(lpDIBBits,lWidth,lHeight);
	::GlobalUnlock((HGLOBAL) m_hDIB);

	Invalidate();
}

// 灰度拉伸
void CLocateView::OnStretch() 
{
	if (m_hDIB == NULL)
		return;

	// 点1坐标
	BYTE	bX1;
	BYTE	bY1;
	
	// 点2坐标
	BYTE	bX2;
	BYTE	bY2;
	
	// 锁定DIB
	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);

	// 找到DIB图像象素起始位置
	LPSTR lpDIBBits = ::FindDIBBits(lpDIB);
	
	//(重要)
	bX1 = 100;
	bY1 = 1;
	bX2 = 150;
	bY2 = 255;
	
	BeginWaitCursor();
	
	// 调用GrayStretch()函数进行灰度拉伸
	GrayStretch(lpDIBBits, ::DIBWidth(lpDIB), ::DIBHeight(lpDIB), bX1, bY1, bX2, bY2);

	Invalidate();
	
	// 解除锁定
	::GlobalUnlock((HGLOBAL) m_hDIB);

	EndWaitCursor();
}

// 阈值变换(二值化)
void CLocateView::OnThreshold() 
{

}

// 模板变换
void CLocateView::OnTemplate() 
{
	if (m_hDIB == NULL)
		return;

	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);//获得当前位图

	LPSTR lpDIBBits = ::FindDIBBits(lpDIB);
	int w = ::DIBWidth(lpDIB);
	int h = ::DIBHeight(lpDIB);

	//用自定义的模板消弱背景干扰
	Template(lpDIB);
//	::RobertDIB(lpDIBBits,w,h);

	Invalidate();

	::GlobalUnlock((HGLOBAL) m_hDIB);
}

// 中值滤波
void CLocateView::OnMedianFilter() 
{
	LPSTR	lpDIB;		// 指向DIB的指针
	LPSTR   lpDIBBits;	// 指向DIB象素指针
	int iFilterH;		// 滤波器的高度
	int iFilterW;		// 滤波器的宽度
	int iFilterMX;		// 中心元素的X坐标
	int iFilterMY;		// 中心元素的Y坐标
	
	// 锁定DIB
	if (m_hDIB == NULL)
		return;



	lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);

    if(::DIBNumColors(lpDIB) != 256)  //不是256色位图不作任何处理
	{
		return ;
    }
	
	// 找到DIB图像象素起始位置
	lpDIBBits = ::FindDIBBits(lpDIB);
	
	// 初始化变量值(重要)
	iFilterH = 3;
	iFilterW = 3;
	iFilterMX = 1;
	iFilterMY = 1;
		
	BeginWaitCursor();
	
	// 调用MedianFilter()函数中值滤波
	if (MedianFilter(lpDIBBits, ::DIBWidth(lpDIB), ::DIBHeight(lpDIB), 
		iFilterH, iFilterW, iFilterMX, iFilterMY))
	{
		Invalidate();
	}
	else
	{
		MessageBox("分配内存失败!", "系统提示" , MB_ICONINFORMATION | MB_OK);
	}
	
	// 解除锁定
	::GlobalUnlock((HGLOBAL) m_hDIB);
	
	EndWaitCursor();

	CStatusBar* pStatus=(CStatusBar*) 
    AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR); 
    pStatus->SetPaneText(0,"去噪音处理"); 
}

// 核心代码: 筛选可能存在拍照的区域
void CLocateView::OnFiltrate() 
{
	if (m_hDIB == NULL)
		return;

	long lRows = 0;	// 有效的行数
	long L,K;		// 用于迭代的行列号
	long lDist;		// 跳变点的间距
	CPoint s[1000];	// 某一段跳变点的起始坐标
	CPoint e[1000];	// 某一段跳变点的终止坐标
	long   r[1000];	// 每行的跳变点数

	LPSTR lpDIB      = (LPSTR)::GlobalLock((HGLOBAL)m_hDIB);
	LPSTR lpDIBBits  = ::FindDIBBits(lpDIB);	
	long  lWidth     = ::DIBWidth(lpDIB);
	long  lHeight    = ::DIBHeight(lpDIB);	
	long  lLineBytes = WIDTHBYTES(lWidth * 8);

	#define VALUE(i,j) (*((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j))

	BOOL* lFlag = new BOOL[lHeight]; // 记录每一行是否存在有效跳边点段
	memset(lFlag,0,sizeof(BOOL)*lHeight);

	for(L = 0; L < lHeight; L++)
	{
		for (K = 0,lDist = -1; K < lWidth; K++)
		{
			// 跳过黑色点		
			while (VALUE(L,K) == 0)	
			{
				K++;
				if (lDist >= 0)
				{
					lDist++;
				}
			}	

			if (lDist == -1)
			{
				s[lRows] = e[lRows] = CPoint(L,K);
				r[lRows] = 1;
				lDist = 0;
			}
			else if (lDist >= 0 && lDist <= m_lMaxDist)
			{
				e[lRows].y = K;	
				r[lRows]++;
				lDist = 0;
			}
			else if (lDist > m_lMaxDist && r[lRows] < m_lMinDotNum)
			{
				s[lRows].y = K;
				e[lRows].y = K;
				r[lRows] = 0;
				lDist = 0;
			}
			else if (lDist > m_lMaxDist && r[lRows] >= m_lMinDotNum)
			{
				lRows++;
				break;
			}
		}// end for K
	}// end for L 	
	

	CPoint pts[1000],pte[1000];

	for (int i = 0; i < lRows; i++)
	{
		lFlag[s[i].x] = TRUE;	// 该行有效
		pts[s[i].x] = s[i];
		pte[s[i].x] = e[i];
		
//		for (int col = s[i].y; col < e[i].y; col++)
//			VALUE(s[i].x,col) = 255;
	}	

	::GlobalUnlock((HGLOBAL)GetHDIB());

	//////////////////////////////////////////////////////////////////////////
	CArray<group,group> grpArray;	// 存放候选区域

	int nDist = -1;
	
	int nCurS;
	int nCurE;

	for (i = 0; i < lHeight; i++)
	{
		if (lFlag[i] == FALSE)
		{
			if (nDist != -1) // 为-1的时候不考虑,只管跳过
			{
				nCurE = i;
				while (lFlag[i] == FALSE && i < lHeight)
				{
					i++;
					nDist++;
				}
				if (nDist > m_nMaxGap) // 之间的行间距太大
				{
					if ((nCurE - nCurS) > m_nMinHeight)
					{
						group grpTemp;
						grpTemp.s = nCurS;
						grpTemp.e = nCurE;
						grpArray.Add(grpTemp);
					}
					nDist = -1;			// 重新置为-1
				}
				else
				{
					nCurE = i;
				}
			}
		}
		else // TRUE
		{
			if (nDist == -1)	// 这一行将要成为一个区域的起始行
			{
				nCurS = nCurE = i;
				nDist = 0;
			}
			else
			{
				// 求当前的跳变点左端离起始行的跳变点左端距离
				if (abs(pts[i].y - pts[nCurS].y) > m_nMaxOffset)
				{
					nCurE = i; // 一段结束

					if ((nCurE - nCurS) > m_nMinHeight)
					{
						group grpTemp;
						grpTemp.s = nCurS;
						grpTemp.e = nCurE;
						grpArray.Add(grpTemp);
					}
					nDist = -1;
				}
				else
				{
					nCurE = i;
					nDist = 0;
				}
			}
		}
	}

	//////////////////////////////////////////////////////////////////////////
	CArray<CRect,CRect> rcArray;
	for (i = 0; i < grpArray.GetSize(); i++)
	{
		for (int j = grpArray[i].s; j <= grpArray[i].e; j++)
		{
			if (lFlag[j] == TRUE)
			{
				for (int col = pts[j].y; col < pte[j].y; col++)
					VALUE(pts[j].x,col) = 255;
			}
		}

		CRect rcTemp;
		double left = 0,right = 0;
		int lines = 0;
		for (j = grpArray[i].s; j <= grpArray[i].e; j++)
		{
			if (lFlag[j] == TRUE)
			{
				left += pts[j].y;
				right += pte[j].y;
				lines++;
			}
		}
		rcTemp.left = long(left / lines);
		rcTemp.right = long(right / lines);
		rcTemp.top = grpArray[i].s;
		rcTemp.bottom = grpArray[i].e;

		if (rcTemp.Width() > rcTemp.Height() && rcTemp.Width() > m_nMinWidth
			&& rcTemp.Height() > m_nMinHeight)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -