📄 locateview.cpp
字号:
// 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>
#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)
//}}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 = 10; // 车牌照的最小高度
m_nMinWidth = 80; // 车牌照的最小宽度
}
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; // 照片文件路径
CFileDialog dlg(TRUE,NULL,NULL,0,"JPEG Files (*.jpg)|*.jpg||",this);
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 Files (*.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();
}
// 直方图均衡化
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()
{
if (m_hDIB == NULL)
return;
unsigned char * lpSrc; //指向原图像象素点的指针
LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)m_hDIB);//获得当前位图
LPSTR lpDIBBits = ::FindDIBBits(lpDIB);
LONG lWidth = ::DIBWidth(lpDIB); //DIB 宽度
LONG lHeight = ::DIBHeight(lpDIB); //DIB 高度
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 8);
long lCount[256];
for(long i=0;i<256;i++)
{
lCount[i]=0; //清零
}
if(::DIBNumColors(lpDIB) != 256) //256色位图不作任何处理
{
return;
}
for(i = 0; i < lHeight; i++)
{
for(long j = 0; j < lWidth; j++)
{
// lpSrc=(unsigned char *)lpDIB+lLineBytes*i+j;
lpSrc=(unsigned char *)lpDIBBits+lLineBytes*i+j;
lCount[*(lpSrc)]++;
}
}
//求窗口变换的上限和下限
long temp[16];
int k=0;
for(k=0;k<16;k++)
{
temp[k]=0;
for(i=k*16;i<(k+1)*16;i++)
temp[k]+=lCount[i];
}
long max=0;
int t=0;
for(k=15;k>=0;k--)
{
if(temp[k]>max)
{
max=temp[k];
t=k;
}
}
int bLow=0,bUp=0;
bLow=(t-1)*16;
// bUp=(t+5)*16;
// bLow=100;
bUp=255;
// 阈值(重要)
INT bThre=(INT)((2*bUp+bLow)/3);
// INT bThre = 150;
BeginWaitCursor();
// 调用ThresholdTrans()函数进行阈值变换
ThresholdTrans(lpDIBBits, ::DIBWidth(lpDIB), ::DIBHeight(lpDIB), bThre);
Invalidate();
::GlobalUnlock((HGLOBAL) m_hDIB);
EndWaitCursor();
}
// 模板变换
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
lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
// 找到DIB图像象素起始位置
lpDIBBits = ::FindDIBBits(lpDIB);
// 初始化变量值(重要)
iFilterH = 5;
iFilterW = 1;
iFilterMX = 0;
iFilterMY = 2;
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();
}
// 核心代码: 筛选可能存在拍照的区域
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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -