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

📄 barrecogview.cpp

📁 采用Visual C++开发平台开发了一个条形码识别系统。该系统采用图像处理技术对条形码图像的噪声进行处理
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -