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

📄 zxdib.cpp

📁 利用web camera对目标进行特征跟踪的程序 对于初学机器视觉的有些帮助
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// ZXDib.cpp: implementation of the CZXDib class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ZXDib.h"
#include <math.h>

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CZXDib::CZXDib()
{

}

CZXDib::~CZXDib()
{

}
////////////////////////////////////////////////////////////////////////////
// 从内存中装入图像数据到指定的矩阵: (只对256色和24位真彩色)
// FileName 是图像名字
// ppBitmapData 是待存储的图像一维向量的指针地址
// dwWidth , dwHeight 分别是图像的宽度和长度
// flag 返回图像位数(8或者24)
////////////////////////////////////////////////////////////////////////////
bool CZXDib::LoadVectorFromBMPFile(CString &FileName, BYTE *&pBitmapData, DWORD &dwHeight, DWORD &dwWidth,WORD &flag)
{
	DWORD i,skip,position;

	//打开制定图像文件FileName:
	CFile File;  
	if(!File.Open(FileName,CFile::modeRead|CFile::typeBinary)){
		AfxMessageBox(FileName+" 打不开!LoadBitmap"+FileName);
		return FALSE;
	}
	FileName = File.GetFilePath();
	//读文件头:
	BITMAPFILEHEADER bfh;
	File.Read(&bfh,sizeof(BITMAPFILEHEADER));
	if(bfh.bfType!=0x4d42)  //'BM' 不是bmp位图,返回
		return FALSE;

	//读位图信息头:
	BITMAPINFO bmi;
	File.Read(&bmi,sizeof(BITMAPINFO));
	
	dwHeight = bmi.bmiHeader.biHeight;
	dwWidth = bmi.bmiHeader.biWidth;
	//1,4,8,24 分别对应2,16,256,真彩色
	flag = bmi.bmiHeader.biBitCount; 
	if(flag == 24) 
		dwWidth *= 3; //若是真彩色,则把宽度变为三倍
	DWORD dwSize = dwHeight * dwWidth; //位图矩阵大小
	DWORD dReadWidth = (dwWidth+3)/4*4; //实际存储的宽度
    
	//重新申请空间:
	if(pBitmapData) delete pBitmapData;
	pBitmapData = (BYTE*) new BYTE[dwSize];
	if(!pBitmapData) return FALSE;

	//设置每行跳转的字节数
	skip = dReadWidth - dwWidth; 
	//设置初始的矩阵存放位置:
	position = dwSize - dwWidth;
	//读文件:
	File.Seek(bfh.bfOffBits,0);
	for(i=0;i<dwHeight;i++)
	{
		File.ReadHuge(pBitmapData+position,dwWidth);	
		File.Seek(skip,1);
		position -= dwWidth; //调整指针
	}

	File.Close();
	
	if(flag==24)
		dwWidth /= 3; //恢复图像的宽度:

	return true;
}
////////////////////////////////////////////////////////////////////
//将一维向量图像数据写入文件
// FileName 文件名
// pBitmapData 一维向量指针
// dwWidth,dwHeight 图像的宽度和长度
// flag : 图像的类型
////////////////////////////////////////////////////////////////////
bool CZXDib::WriteBMPFileFromVector(CString &FileName, BYTE *pBitmapData,DWORD dwHeight,DWORD dwWidth,WORD flag)
{
	//参数有效性检测:
	if(!pBitmapData) 
		return FALSE;
	if((flag!=8)&&(flag!=24))
		return FALSE; 

	if(flag == 24)
		dwWidth *= 3;
	
	DWORD dwWriteWidth = (dwWidth+3)/4*4;
	DWORD dwWriteSize = dwHeight * dwWriteWidth;
	
	//打开文件:
	CFile File;
	File.Open(FileName,CFile::modeCreate|CFile::modeWrite);

	BITMAPFILEHEADER BitmapFileHeader;
	if(flag == 24) 
		BitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFO)-4;
	else 
		BitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFO)-4+256*sizeof(RGBQUAD); 
	BitmapFileHeader.bfReserved1 = 0;
	BitmapFileHeader.bfReserved2 = 0;
	BitmapFileHeader.bfType = 0x4d42;//'BM'
	BitmapFileHeader.bfSize =  dwWriteSize + BitmapFileHeader.bfOffBits;

	File.Write(&BitmapFileHeader,sizeof(BITMAPFILEHEADER));

	BITMAPINFO BitmapInfo;
	BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFO)-4;//无论是黑白图还是彩图都是40
	BitmapInfo.bmiHeader.biBitCount = flag;
	BitmapInfo.bmiHeader.biHeight = dwHeight;
	if(flag ==24) 
		BitmapInfo.bmiHeader.biWidth = dwWidth/3;
	else 
		BitmapInfo.bmiHeader.biWidth = dwWidth;
	BitmapInfo.bmiHeader.biSizeImage = dwWriteSize;
	BitmapInfo.bmiHeader.biCompression= 0;
	BitmapInfo.bmiHeader.biPlanes = 1;
	BitmapInfo.bmiHeader.biClrImportant = 0;
	BitmapInfo.bmiHeader.biClrUsed = 0;
	BitmapInfo.bmiHeader.biXPelsPerMeter = 
		BitmapInfo.bmiHeader.biYPelsPerMeter=0;
	BitmapInfo.bmiColors[0].rgbBlue = 
		BitmapInfo.bmiColors[0].rgbGreen=
		BitmapInfo.bmiColors[0].rgbRed=
		BitmapInfo.bmiColors[0].rgbReserved=0;
	

	File.Write(&BitmapInfo,sizeof(BITMAPINFO));

	//若是256色图像则,写调色板
	if( flag==8 )
	{
		for(int i=1; i<256; i++)
		{
			BYTE temp = (BYTE) i;
			File.Write(&temp,1);
			File.Write(&temp,1);
			File.Write(&temp,1);
			temp = 0;
			File.Write(&temp,1);
		}
	}

	//写文件:
	DWORD position = dwWidth*dwHeight - dwWidth;
	DWORD skip = dwWriteWidth - dwWidth;

	File.Seek(BitmapFileHeader.bfOffBits,0);
	for(DWORD i=0; i<dwHeight; i++)
	{
		File.Write(pBitmapData+position,dwWidth);
		File.Seek(skip,1);
		position -= dwWidth;
	}
	char ch='/0';
	File.Write(&ch,sizeof(char));
	File.Close();

	return true;
}
/////////////////////////////////////////////////////////////////////////
//
//  寻找下一个文件名
//
/////////////////////////////////////////////////////////////////////////
bool CZXDib::FindNextFileName(CString &FileName,int iStep)
{

	int position = FileName.Find(".bmp");
	if(position<0) 
		position = FileName.Find(".BMP");
	position--;

	while(iStep>0)
	{
		char ch =  FileName.GetAt(position);
		if(ch<'9'){
			ch++;
			FileName.SetAt(position,ch);
		}
		else{
			FileName.SetAt(position,'0');
			ch = FileName.GetAt(position-1);
			if(ch<'9')	{
				ch++;
				FileName.SetAt(position-1,ch);
			}
			else	{
				FileName.SetAt(position-1,'0');
				ch = FileName.GetAt(position-2);
				if(ch<'9'){
					ch++;
					FileName.SetAt(position-2,ch);
				}
				else{
					FileName.SetAt(position-2,'0');
					ch = FileName.GetAt(position-3);
					ch++;
					FileName.SetAt(position-3,ch);
				}
			}
		}
		iStep--;
	}
	return true;
}
////////////////////////////////////////////////////
//
//  将向量数据转换为BMP图像向量:
//
////////////////////////////////////////////////////
bool CZXDib::TranslateVectorToBitmap(DWORD dwHeight,DWORD dwWidth,BYTE* pVector,BYTE*& pBitmapData,WORD flag)
{
	DWORD i,j;
	if(flag==24) dwWidth *= 3;
	else 
		if(flag!=8) return false;
	DWORD dwWriteWidth = (dwWidth+3)/4*4;

	if(pBitmapData) delete []pBitmapData;
	pBitmapData = (BYTE*) new BYTE[dwHeight*dwWriteWidth];
	
	for(i=0; i<dwHeight; i++)
	for(j=0; j<dwWidth; j++)
		pBitmapData[(dwHeight-1-i)*dwWriteWidth+j]   = pVector[i*dwWidth+j];
	
	return true;
}
////////////////////////////////////////////////////
//
//  将BMP图像向量转换为向量数据:
//
////////////////////////////////////////////////////
bool CZXDib::TranslateBitmapToVector(DWORD dwHeight,DWORD dwWidth,BYTE* pBitmapData,BYTE*& pVector,WORD flag)
{
	DWORD i,j;
	if(flag==24) dwWidth *= 3;
	else 
		if(flag!=8) return false;
	DWORD dwWriteWidth = (dwWidth+3)/4*4;

	if(pVector) delete []pVector;
	pVector = (BYTE*) new BYTE[dwHeight*dwWriteWidth];
	
	for(i=0; i<dwHeight; i++)
	for(j=0; j<dwWidth; j++)
		pVector[i*dwWidth+j] = pBitmapData[(dwHeight-1-i)*dwWriteWidth+j];
	
	return true;
}
///////////////////////////////////////////////////////////////////
//
//  得到BMP位图的头信息指针
//
///////////////////////////////////////////////////////////////////
bool CZXDib::GetBMPFileHeader(BITMAPFILEHEADER &bfh,CString &FileName)
{
    CFile File;
	if(!File.Open(FileName,CFile::modeRead|CFile::typeBinary)){
		AfxMessageBox(FileName+" 打不开!LoadBitmap");
		return FALSE;
	}
	File.Read(&bfh,sizeof(BITMAPFILEHEADER));
	File.Close();

   return true;
}
///////////////////////////////////////////////////////////////////
//
//  得到BMP位图的头信息指针
//
///////////////////////////////////////////////////////////////////
bool CZXDib::GetBitmapInfo(BITMAPINFO *&bmi, CString &FileName)
{
	CFile File;
	if(!File.Open(FileName,CFile::modeRead|CFile::typeBinary)){
		AfxMessageBox(FileName+" 打不开!LoadBitmap");
		return FALSE;
	}
	
	File.Seek(sizeof(BITMAPFILEHEADER),0);
	
	if(bmi) delete bmi;
	bmi = (BITMAPINFO*) new BYTE[sizeof(BITMAPINFO)+256*sizeof(RGBQUAD)];
	File.Read(bmi,sizeof(BITMAPINFO)+256*sizeof(RGBQUAD));
	
	File.Close();
    return TRUE;
}
////////////////////////////////////////////////////////////////////////////
//
// Sobel算子
/////////////////////////////////////////////////////////////////////////////
bool CZXDib::Sobel(BYTE *& pImage, DWORD dwHeight, DWORD dwWidth)
{
	DWORD i,j;
	double temp1,temp2;
	DWORD Height,Width,dwSize;
	Height = dwHeight-1;
	Width = dwWidth-1;
	dwSize = dwHeight*dwWidth;

	double * pResult=NULL;
	if(!(pResult = (double*) new double[dwHeight*dwWidth]))
	{
		AfxMessageBox("分配空间失败!CZXDib::Sobel pResult");
		return false;
	}

	for(i=1; i<Height; i++)
	for(j=1; j<Width; j++)
	{
		//水平方向
		temp1 = pImage[j+1+(i-1)*dwWidth]+2*pImage[j+1+i*dwWidth]+pImage[j+1+(i+1)*dwWidth]-pImage[j-1+(i-1)*dwWidth]-2*pImage[j-1+i*dwWidth]-pImage[j-1+(i+1)*dwWidth];
		temp1 *= temp1;
		//竖直方向
		temp2 = pImage[j+1+(i+1)*dwWidth]+2*pImage[j+(i+1)*dwWidth]+pImage[j-1+(i+1)*dwWidth]-pImage[j-1+(i-1)*dwWidth]-2*pImage[j+(i-1)*dwWidth]-pImage[j+1+(i-1)*dwWidth];
		temp2 *= temp2;
		pResult[j+i*dwWidth]= sqrt(temp1+temp2);
	}

	for(i=0;i<dwSize;i+=dwWidth)
	{
		pImage[i]=0;
	    pImage[i+dwWidth-1]=0;
	}
	for(j=0;j<dwWidth;j++)
	{
		pImage[j]=0;
		pImage[dwSize-j-1]=0;
	}

	for(i=1; i<Height; i++)
	for(j=1; j<Width; j++)
	{
		if(pResult[j+i*dwWidth]>255) 
			pImage[j+i*dwWidth] = 255;
		else
		pImage[j+i*dwWidth] = (BYTE) pResult[j+i*dwWidth];
	}
	
	delete  pResult;

	return true;
}
////////////////////////////////////////////////////////////////////////////
//
// Sobel算子
/////////////////////////////////////////////////////////////////////////////
bool CZXDib::Sobel(BYTE* pImage, DWORD dwHeight, DWORD dwWidth,double* &pResult)
{
	DWORD i,j;
	double temp1,temp2;
	DWORD Height,Width,dwSize;
	Height = dwHeight-1;
	Width = dwWidth-1;
	dwSize = dwHeight*dwWidth;
	dwSize -= dwWidth;

	if(pResult) delete pResult;
	if(!(pResult = (double*) new double[dwHeight*dwWidth]))
	{
		AfxMessageBox("分配空间失败!CZXDib::Sobel pResult");
		return false;
	}
	
	for(i=1; i<Height; i++)
	for(j=1; j<Width; j++)
	{
		//水平方向
		temp1 = pImage[j+1+(i-1)*dwWidth]+2*pImage[j+1+i*dwWidth]+pImage[j+1+(i+1)*dwWidth]-pImage[j-1+(i-1)*dwWidth]-2*pImage[j-1+i*dwWidth]-pImage[j-1+(i+1)*dwWidth];
		temp1 *= temp1;
		//竖直方向
		temp2 = pImage[j+1+(i+1)*dwWidth]+2*pImage[j+(i+1)*dwWidth]+pImage[j-1+(i+1)*dwWidth]-pImage[j-1+(i-1)*dwWidth]-2*pImage[j+(i-1)*dwWidth]-pImage[j+1+(i-1)*dwWidth];
		temp2 *= temp2;
		pResult[j+i*dwWidth]= sqrt(temp1+temp2);
	}

	for(i=0;i<dwSize;i+=dwWidth)
	{
		pResult[i]=0;
	    pResult[i+dwWidth-1]=0;
	}
	for(j=0;j<dwWidth;j++)
	{
		pResult[j]=0;
		pResult[dwSize-j-1]=0;
	}

	return true;
}
////////////////////////////////////////////////////////////////////////////////////////
//
//  求直方图:
//
////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::Histogram(BYTE *pBitmap, DWORD dwHeight, DWORD dwWidth, BYTE *&pResult)
{
	DWORD i,j,max;

	if(pResult) delete pResult;
	pResult = new BYTE[256];

	DWORD pTemp[256];
	for(i=0; i<256; i++)
		pTemp[i]=0;

	for(j=0; j<dwHeight; j++)
	for(i=0; i<dwWidth; i++)
		pTemp[pBitmap[j*dwWidth+i]]++;

	max = 0;
	for(i=0;i<256; i++)
		if(pTemp[i]>max) max = pTemp[i];

	for(i=0; i<256; i++)
		pResult[i] = (BYTE) (pTemp[i]*255/max);
	
	return true;
}
//////////////////////////////////////////////////////////////////
//
//  将直方图转化为256*256显示矩阵
//
//////////////////////////////////////////////////////////////////
bool CZXDib::TranslateHistogramToVector(BYTE *pHg, BYTE *&pResult)
{
	DWORD i,j,top;

	if(pResult) delete pResult;
	pResult = new BYTE[256*256];
	
	for(i=0; i<256; i++)
	{
		top = 256-pHg[i];
		for(j=0; j<top; j++)
			pResult[j*256+i] = 240;
		for(;j<256;j++)
			pResult[j*256+i] = 0;
	}
	return true;
}
////////////////////////////////////////////////////////////////////////
//
//  直方图平滑:
//
////////////////////////////////////////////////////////////////////////
bool CZXDib::HistogramSmoothBy5Points(BYTE *pHg,int level)
{

⌨️ 快捷键说明

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