📄 barrecogview.cpp
字号:
// BarRecogView.cpp : implementation of the CBarRecogView class
//
#include "stdafx.h"
#include "BarRecog.h"
#include "dib.h"
#include "BarRecogDoc.h"
#include "BarRecogView.h"
#include <string.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CBarRecogView
IMPLEMENT_DYNCREATE(CBarRecogView, CScrollView)
BEGIN_MESSAGE_MAP(CBarRecogView, CScrollView)
//{{AFX_MSG_MAP(CBarRecogView)
ON_COMMAND(Convert, OnConvert)
ON_COMMAND(MedianFilter, OnMedianFilter)
ON_COMMAND(TwoState, OnTwoState)
ON_COMMAND(Recog, OnRecog)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBarRecogView construction/destruction
CBarRecogView::CBarRecogView()
{
// TODO: add construction code here
ImageWidth = 0;
ImageHeight = 0;
ImageArray = NULL;
Step=0;
}
CBarRecogView::~CBarRecogView()
{
}
BOOL CBarRecogView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CScrollView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CBarRecogView drawing
void CBarRecogView::OnDraw(CDC* pDC)
{
CBarRecogDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
if(pDoc->m_DIB.IsValid())
{
int cxDIB=(int)pDoc->m_DIB.Width();
int cyDIB=(int)pDoc->m_DIB.Height();
CRect rcDIB;
rcDIB.top=rcDIB.left=0;
rcDIB.right=cxDIB;
rcDIB.bottom=cyDIB;
CRect rcDest;
if(pDC->IsPrinting())
{
int cxPage=pDC->GetDeviceCaps(HORZRES);
int cyPage=pDC->GetDeviceCaps(VERTRES);
int cxInch=pDC->GetDeviceCaps(LOGPIXELSX);
int cyInch=pDC->GetDeviceCaps(LOGPIXELSY);
rcDest.top=rcDest.left=0;
rcDest.bottom=(int)(((double)cyDIB*cxPage*cyInch)/((double)cxDIB*cxInch));
rcDest.right=cxPage;
}
else
{
rcDest=rcDIB;
}
pDoc->m_DIB.Paint(pDC->m_hDC,&rcDest,&rcDIB);
}
}
void CBarRecogView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal;
// TODO: calculate the total size of this view
sizeTotal.cx = sizeTotal.cy = 100;
SetScrollSizes(MM_TEXT, sizeTotal);
}
/////////////////////////////////////////////////////////////////////////////
// CBarRecogView printing
BOOL CBarRecogView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CBarRecogView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CBarRecogView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CBarRecogView diagnostics
#ifdef _DEBUG
void CBarRecogView::AssertValid() const
{
CScrollView::AssertValid();
}
void CBarRecogView::Dump(CDumpContext& dc) const
{
CScrollView::Dump(dc);
}
CBarRecogDoc* CBarRecogView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CBarRecogDoc)));
return (CBarRecogDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CBarRecogView message handlers
void CBarRecogView::Convert256toGray()
{
CBarRecogDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
WORD wBitCount=pDoc->m_DIB.m_pBMI->bmiHeader.biBitCount;
if(wBitCount!=8)
{
MessageBox("该转换函数只处理8位图像!","系统提示",MB_OK);
return;
}
// 指向DIB象素数据区的指针
LPBYTE lpDIBBits;
// 指向DIB象素的指针
BYTE * lpSrc;
// 图像宽度
LONG lWidth;
// 图像高度
LONG lHeight;
// 图像每行的字节数
LONG lLineBytes;
// 灰度映射表
BYTE bMap[256];
// 计算灰度映射表(保存各个颜色的灰度值),并更新DIB调色板
int i,j;
for (i = 0; i < 256; i ++)
{
// 计算该颜色对应的灰度值
bMap[i] = (BYTE)(0.299 * pDoc->m_DIB.m_pBMI->bmiColors[i].rgbRed +
0.587 * pDoc->m_DIB.m_pBMI->bmiColors[i].rgbGreen +
0.114 * pDoc->m_DIB.m_pBMI->bmiColors[i].rgbBlue + 0.5);
// 更新DIB调色板红色分量
pDoc->m_DIB.m_pBMI->bmiColors[i].rgbRed = i;
// 更新DIB调色板绿色分量
pDoc->m_DIB.m_pBMI->bmiColors[i].rgbGreen = i;
// 更新DIB调色板蓝色分量
pDoc->m_DIB.m_pBMI->bmiColors[i].rgbBlue = i;
// 更新DIB调色板保留位
pDoc->m_DIB.m_pBMI->bmiColors[i].rgbReserved = 0;
}
// 找到DIB图像象素起始位置
lpDIBBits = pDoc->m_DIB.m_pBits;
// 获取图像宽度
lWidth = (LONG)pDoc->m_DIB.Width();
// 获取图像高度
lHeight = (LONG)pDoc->m_DIB.Height();
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 更换每个象素的颜色索引(即按照灰度映射表换成灰度值)
//逐行扫描
for(i = 0; i < lHeight; i++)
{
//逐列扫描
for(j = 0; j < lWidth; j++)
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 变换
*lpSrc = bMap[*lpSrc];
}
}
Step=1;
}
void CBarRecogView::OnConvert()
{
// TODO: Add your command handler code here
CBarRecogDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
BeginWaitCursor(); //更改光标形状;
Convert256toGray(); //调用处理函数;
pDoc->SetModifiedFlag(TRUE); //设置脏标记;
pDoc->UpdateAllViews(NULL); //更新视图;
EndWaitCursor(); //恢复光标;
}
BOOL CBarRecogView::MedianFilterDIB()
{
CBarRecogDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if(pDoc->m_DIB.m_pBMI==NULL)return FALSE;
WORD wBitCount=pDoc->m_DIB.m_pBMI->bmiHeader.biBitCount;
if(wBitCount!=8)
{
MessageBox("该均值滤波只处理8位图像!","系统提示",MB_OK);
return FALSE;
}
if(Step<2)
{
if(MessageBox("该图像没有进行灰度转换和二值化操作!\n如果不执行这些操作,可能会产生错误结果!\n\n按“否”可中止当前操作\n按“是”继续执行滤波操作","提示",MB_ICONEXCLAMATION | MB_YESNO)==7)return FALSE;
}
DWORD m_dwSizeImage=pDoc->m_DIB.m_pBMI->bmiHeader.biSizeImage;
LPBYTE m_lpImageCopy=(BYTE*)malloc(m_dwSizeImage);
if(m_lpImageCopy==NULL)
{
SetCursor(LoadCursor(NULL,IDC_ARROW));
AfxMessageBox("Memory Allocate error");
return FALSE;
}
memcpy(m_lpImageCopy,pDoc->m_DIB.m_pBits,m_dwSizeImage);
DWORD nWidth=pDoc->m_DIB.Width();
DWORD nHeight=pDoc->m_DIB.Height();
DWORD lRowBytes=WIDTHBYTES(nWidth*((DWORD)wBitCount));
LPBYTE lpData=pDoc->m_DIB.m_pBits;
LPBYTE lpOldBits=m_lpImageCopy;
DWORD i,j;
BYTE *p1,*p2,*p3,*p4,*p5;
if(wBitCount==8)
{
for(i=2;i<nHeight-2;i++)
{
for(j=0;j<nWidth;j++)
{
p1=lpOldBits+lRowBytes*(i-2)+(j);
p2=lpOldBits+lRowBytes*(i-1)+(j);
p3=lpOldBits+lRowBytes*(i)+(j);
p4=lpOldBits+lRowBytes*(i+1)+(j);
p5=lpOldBits+lRowBytes*(i+2)+(j);
int t=0,temp[5];
temp[0]=(int)(*p1);
temp[1]=(int)(*p2);
temp[2]=(int)(*p3);
temp[3]=(int)(*p4);
temp[4]=(int)(*p5);
for(int x=0;x<5;x++)
{
t+=temp[x];
}
if((t/5)>127)
*(pDoc->m_DIB.m_pBits+lRowBytes*(i)+(j))=(BYTE)255;
else
*(pDoc->m_DIB.m_pBits+lRowBytes*(i)+(j))=(BYTE)0;
}
}
}
Step=3;
return TRUE;
}
void CBarRecogView::OnMedianFilter()
{
// TODO: Add your command handler code here
CBarRecogDoc* pDoc = GetDocument();
BeginWaitCursor(); //更改光标形状;
if(MedianFilterDIB()!=FALSE) //调用处理函数;
MedianFilterDIB(); //二次滤波
pDoc->SetModifiedFlag(TRUE); //设置脏标记;
pDoc->UpdateAllViews(NULL); //更新视图;
EndWaitCursor(); //回复光标
}
BOOL CBarRecogView::TwoStateMethord()
{
CBarRecogDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
WORD wBitCount=pDoc->m_DIB.m_pBMI->bmiHeader.biBitCount;
if(wBitCount!=8)
{
MessageBox("该函数只处理8位图像!","系统提示",MB_OK);
return FALSE;
}
if(Step<1)
{
if(MessageBox("该图像没有进行灰度转换!\n如果该图不是灰度图,可能会产生错误结果!\n\n按“否”可中止当前操作\n按“是”继续执行二值化操作","提示",MB_ICONEXCLAMATION | MB_YESNO)==7)return FALSE;
}
int i,j;
unsigned char *lpSrc;
// if(pDoc->m_hDIB == NULL)
// return ;
// LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->m_hDIB);
LPBYTE lpDIBBits=pDoc->m_DIB.m_pBits;
int cxDIB = (int)pDoc->m_DIB.Width(); // Size of DIB - x
int cyDIB = (int)pDoc->m_DIB.Height(); // Size of DIB - y
long lLineBytes = WIDTHBYTES(cxDIB * 8); // 计算图像每行的字节数
const float c1=150,c2=2.5;
// 每行
for(i = 0; i < cyDIB; i++)
{
// 每列
for(j = 0; j < cxDIB; j++)
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (cyDIB - 1 - i) + j;
// 计算新的灰度值
if(*lpSrc<160) *lpSrc=BYTE(0);
else *lpSrc = BYTE(255);
}
}
//::GlobalUnlock((HGLOBAL) pDoc->m_hDIB);
Invalidate(TRUE);
Step=2;
return TRUE;
}
void CBarRecogView::OnTwoState()
{
// TODO: Add your command handler code here
CBarRecogDoc* pDoc = GetDocument();
BeginWaitCursor(); //更改光标形状;
TwoStateMethord(); //调用处理函数;
pDoc->SetModifiedFlag(TRUE); //设置脏标记;
pDoc->UpdateAllViews(NULL); //更新视图;
EndWaitCursor(); //恢复光标
}
BOOL CBarRecogView::PreProcess()
{
CBarRecogDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
WORD wBitCount=pDoc->m_DIB.m_pBMI->bmiHeader.biBitCount;
if(wBitCount!=8)
{
MessageBox("该识别处理函数只处理8位图像!","系统提示",MB_OK);
Step=3;
return FALSE;
}
if(Step<3)
{
if(MessageBox("该图像没有进行灰度转换,二值化和滤波操作!\n如果不执行这些操作,可能会产生错误结果!\n\n按“否”可中止当前操作\n按“是”继续进行识别操作","提示",MB_ICONEXCLAMATION | MB_YESNO)==7)return FALSE;
}
ImageWidth = (long)pDoc->m_DIB.Width();
ImageHeight = (long)pDoc->m_DIB.Height();
ImageArray = pDoc->m_DIB.m_pBits;
DWORD lRowBytes=WIDTHBYTES(ImageWidth*((DWORD)8));
int i, j;
int tempMax;
int tempArray[1000];
//进行水平方向和垂直方向上的直方图统计
for(i=0; i<ImageHeight; i++)
arPixelV[i] = 0;
for(i=0; i<ImageWidth; i++)
arPixelH[i] = 0;
for(i=0; i<ImageHeight; i++)
{
for(j=0; j<ImageWidth; j++)
{
if(*(ImageArray+lRowBytes*(i)+(j))==(BYTE)0)
{
arPixelV[i] += 1;
arPixelH[j] += 1;
}
}
}
//寻找包含条形码的区域,
//线寻找水平方向上黑象素最大的行
tempMax = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -