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

📄 main.cpp

📁 大恒摄像机开发范例程序 有利于大家二次开发
💻 CPP
字号:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Main.h"

//定义自己的0
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define  MY_ZERO 0.000000001

//const
const int DeviceNum = 1;
const HV_RESOLUTION Resolution = RES_MODE0;
const HV_SNAP_MODE SnapMode = CONTINUATION;
const HV_BAYER_LAYOUT Layout = BAYER_GR;
const HV_BAYER_CONVERT_TYPE ConvertType = BAYER2RGB_NEIGHBOUR;
const long Gain = 8;
const long ExposureTint_Upper = 60;
const long ExposureTint_Lower = 1000;

const long ShutterDelay = 0;
const long ADCLevel = ADC_LEVEL2;
const int XStart = 0;
const int YStart = 0;
const int HV_Width = 800;
const int HV_Height = 600;

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMainFrm *MainFrm;
//---------------------------------------------------------------------------
__fastcall TMainFrm::TMainFrm(TComponent* Owner)
    : TForm(Owner)
{
	// TODO: add member initialization code here
	/*
	 *	初始化所有成员变量,同时打开数字摄像机
	 */
	m_bStart		= FALSE;
	
	m_pBmpInfo		= NULL;
	m_pImageBuffer	= NULL;

	m_pFile			= NULL;
	m_ps			= NULL;
	m_psCompressed	= NULL;

	m_nTimeFrame	= 0;

        Start1->Enabled = true;
        Stop1->Enabled = false;

	for(int i=0;i<256;i++)
	{
		m_pLutR[i] = i;
		m_pLutG[i] = i;
		m_pLutB[i] = i;

	}

	//	打开数字摄像机 1
	HVSTATUS status = BeginHVDevice(1, &m_hhv);
	//	检验函数执行状态,如果失败,则返回错误状态消息框
	HV_VERIFY(status);

}
//---------------------------------------------------------------------------
void __fastcall TMainFrm::FormClose(TObject *Sender, TCloseAction &Action)
{
	/*
	 *	用户在没有通过菜单项正常关闭数字摄像机采集,	
	 *	而直接关闭应用程序时,应保证数字摄像机采集被关闭
	 */
	if (m_bStart)
        {
                Stop1Click(Sender);
	}

}
//---------------------------------------------------------------------------

void __fastcall TMainFrm::FormDestroy(TObject *Sender)
{
	HVSTATUS status = STATUS_OK;
	
	//	关闭数字摄像机,释放数字摄像机内部资源
	status = EndHVDevice(m_hhv);
	HV_VERIFY(status);

	//	回收图像缓冲区
	delete []m_pRawBuffer;
	delete []m_pImageBuffer;

}
//---------------------------------------------------------------------------
void __fastcall TMainFrm::FormCreate(TObject *Sender)
{
	/*
	*	初始化数字摄像机硬件状态,用户也可以在其他位置初始化数字摄像机,
	*	但应保证数字摄像机已经打开,建议用户在应用程序初始化时,
	*	同时初始化数字摄像机硬件。
	*/

	//	设置数字摄像机分辨率
	HVSetResolution(m_hhv, Resolution);		
	
	//	采集模式,包括 CONTINUATION(连续)、TRIGGER(外触发)
	HVSetSnapMode(m_hhv, SnapMode);
	
	//  设置各个分量的增益
	for (int i = 0; i < 4; i++){
		HVAGCControl(m_hhv, RED_CHANNEL + i, Gain);
	}
	
	//	设置曝光时间
    SetExposureTime(HV_Width,ExposureTint_Upper,ExposureTint_Lower);

	//  设置ADC的级别
	HVADCControl(m_hhv, ADC_BITS, ADCLevel);
	
	/*
	*	视频输出窗口,即视频输出范围,输出窗口取值范围必须在输入窗口范围以内,
	*  视频窗口左上角X坐标和窗口宽度应为4的倍数,左上角Y坐标和窗口高度应为2的倍数
	*	输出窗口的起始位置一般设置为(0, 0)即可。
	*/
	HVSetOutputWindow(m_hhv, XStart, YStart, HV_Width, HV_Height);
	
	//	m_pBmpInfo即指向m_chBmpBuf缓冲区,用户可以自己分配BTIMAPINFO缓冲区	
	m_pBmpInfo								= (BITMAPINFO *)m_chBmpBuf;
	//	初始化BITMAPINFO 结构,此结构在保存bmp文件、显示采集图像时使用
	m_pBmpInfo->bmiHeader.biSize			= sizeof(BITMAPINFOHEADER);
	//	图像宽度,一般为输出窗口宽度
	m_pBmpInfo->bmiHeader.biWidth			= HV_Width;
	//	图像宽度,一般为输出窗口高度
	m_pBmpInfo->bmiHeader.biHeight			= HV_Height;

	/*
	 *	以下设置一般相同,
	 *	对于低于8位的位图,还应设置相应的位图调色板
	 */
	m_pBmpInfo->bmiHeader.biPlanes			= 1;
	m_pBmpInfo->bmiHeader.biBitCount		= 24;
	m_pBmpInfo->bmiHeader.biCompression		= BI_RGB;
	m_pBmpInfo->bmiHeader.biSizeImage		= 0;
	m_pBmpInfo->bmiHeader.biXPelsPerMeter	= 0;
	m_pBmpInfo->bmiHeader.biYPelsPerMeter	= 0;
	m_pBmpInfo->bmiHeader.biClrUsed			= 0;
	m_pBmpInfo->bmiHeader.biClrImportant	= 0;
	
	/*
	*	分配原始图像缓冲区,一般用来存储采集图像原始数据
	*  一般图像缓冲区大小由输出窗口大小和视频格式确定。
	*/
	m_pRawBuffer = new BYTE[HV_Width * HV_Height];
	assert(m_pRawBuffer);

	/*
	分配Bayer转换后图像数据缓冲
	*/
	m_pImageBuffer = new BYTE[HV_Width * HV_Height * 3];
	assert(m_pImageBuffer);
}


//---------------------------------------------------------------------------
void __fastcall TMainFrm::Start1Click(TObject *Sender)
{
	// TODO: Add your command handler code here
	HVSTATUS status = STATUS_OK;
	
	WORD wVer = 0;
	HRESULT hr = S_OK;
	BOOL bRVal = TRUE;

	//CFileDialog dlg(FALSE , "*.avi", NULL ,OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY, "AVI Files(*.avi)|*.avi", this);
	//if (dlg.DoModal() == IDOK)
        SaveDialog1->Filter = "AVI Files(*.avi)|*.avi";
        if(SaveDialog1->Execute())
        {
		wVer = HIWORD(VideoForWindowsVersion());
		if ( !(wVer < 0x010a)){   /* oops, we are too old, blow out of here */
			AVIFileInit();

			// For some reason AVIFileOpen will not shrink the file even with OF_CREATE set
			::DeleteFile(SaveDialog1->FileName.c_str());

			//	创建AVI文件
			hr = AVIFileOpen(&m_pFile, // returned file pointer
							SaveDialog1->FileName.c_str(), // file name
							OF_WRITE | OF_CREATE, // mode to open file with
							NULL); // use handler determined
			// from file extension....
			if (hr != AVIERR_OK){
				bRVal = FALSE;
			}
			else{
				AVISTREAMINFO strhdr;		//AVI文件信息
				memset(&strhdr, 0, sizeof(strhdr));
				
				strhdr.fccType = streamtypeVIDEO;// stream type
				strhdr.fccHandler = 0;
				strhdr.dwScale = 1;
				strhdr.dwRate = 15; // rate fps
				strhdr.dwSuggestedBufferSize = HV_Width * HV_Height * 3;
				SetRect(&strhdr.rcFrame, 0, 0, HV_Width, HV_Height);// rectangle for stream

				// And create the stream;
				HRESULT hr = AVIFileCreateStream(m_pFile, // file pointer
												&m_ps, // returned stream pointer
												&strhdr); // stream header
				if (hr != AVIERR_OK){
					bRVal = FALSE;
				}
				else{
					AVICOMPRESSOPTIONS opts;
					AVICOMPRESSOPTIONS FAR * aopts[1] = {&opts};
					memset(&opts, 0, sizeof(opts));
					
					if (!AVISaveOptions(NULL, 0, 1, &m_ps, (LPAVICOMPRESSOPTIONS FAR *) &aopts)){
						bRVal = FALSE;
					}
					else{
						hr = AVIMakeCompressedStream(&m_psCompressed, m_ps, &opts, NULL);
						if (hr != AVIERR_OK) {
							bRVal = FALSE;
						}
						else{
							hr = AVIStreamSetFormat(m_psCompressed, 
								0,
								m_pBmpInfo, // stream format
								sizeof(BITMAPINFOHEADER) // format size
								);
							if (hr != AVIERR_OK) {
								bRVal = FALSE;
							}
						}
					}
				}
			}	
		}
			
		if ( bRVal) {
			/*
			 *	初始化数字摄像机采集图像到内存的控制,
			 *	指定回调函数SnapThreadCallbackEx和用户参数m_hWnd
			 */
			status = HVOpenSnap(m_hhv, SnapThreadCallback, this->Handle);
			HV_VERIFY(status);
			if ( HV_SUCCESS(status)) {			//已经打开SnapEx环境				
				//	启动数字摄像机采集图像到内存

	                        BYTE *ppBuf[1];
	                        ppBuf[0] = m_pRawBuffer;
	                        status = HVStartSnap(m_hhv, ppBuf,1);
                                
				HV_VERIFY(status);
				if (HV_SUCCESS(status)) {
					m_bStart = TRUE;			//标志开始图像的采集和压缩
                                        Start1->Enabled = false;
                                        Stop1->Enabled = true;
				}
				else{
					HVCloseSnap(m_hhv);
				}
			}
		}
		
		//	终止AVI文件
		if ( !m_bStart) {
			if (m_ps){
				AVIStreamClose(m_ps);
				m_ps = NULL;
			}
			if (m_psCompressed){
				AVIStreamClose(m_psCompressed);
				m_psCompressed = NULL;
			}
			if (m_pFile){
				AVIFileClose(m_pFile);
				m_pFile = NULL;
			}
			AVIFileExit();
		}		
	}
}
//---------------------------------------------------------------------------

void __fastcall TMainFrm::Stop1Click(TObject *Sender)
{

	//	关闭采集图像到内存控制,释放数字摄像机资源
	HVCloseSnap(m_hhv);

	//	终止AVI文件
	if (m_ps){
		AVIStreamClose(m_ps);
		m_ps = NULL;
	}
	if (m_psCompressed){
		AVIStreamClose(m_psCompressed);
		m_psCompressed = NULL;
	}
	if (m_pFile){
		AVIFileClose(m_pFile);
		m_pFile = NULL;
	}	
	AVIFileExit();

	m_nTimeFrame	= 0;
	m_bStart		= FALSE;

        Start1->Enabled = true;
        Stop1->Enabled = false;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
/*
	函数:
		SnapThreadCallback
	输入参数:
		SNAP_INFO *pInfo		SNAP_INFO结构包括当前数字摄像机SNAP执行状态
	输出参数:
		int
	说明:
		数字摄像机采集到内存回调函数,但用户一般不用调用,由用户提供给SDK使用,
		用户在回调函数内实现对采集数据的处理和显示即可
 */
int CALLBACK TMainFrm::SnapThreadCallback(HV_SNAP_INFO *pInfo)
{
	HWND hwnd = (HWND)(pInfo->pParam);

	/*
	 *	发送自定义消息WM_SNAP_EX_CHANGE到主窗口,
	 *	同时传入当前可以处理的图像序号
	 *	注意:用SendMessage发送消息,必须等待消息处理完毕后,才能退出整个SendMessage函数
	 */
	::SendMessage(hwnd, WM_SNAP_CHANGE, 0, 0);

	return 1;
}

//-----------------------------------------------------------------------------


/*
	函数:
		OnSnapChange
	输入参数:
		TMessage &Msg			字参数,在消息中为当前可以处理的图像序号
	输出参数:
		LRESULT
	说明:
		实现对采集数据的处理和显示
 */
LRESULT TMainFrm::OnSnapChange(TMessage &Msg)
{
	//	将原始图像数据进行Bayer转换,转换后为24位。
         //同时将原始数据进行上下翻转
	ConvertBayer2Rgb(m_pImageBuffer,m_pRawBuffer,HV_Width,HV_Height,ConvertType,m_pLutR,m_pLutG,m_pLutB,true,Layout);

	if (m_psCompressed) {
		HRESULT hr = AVIStreamWrite(m_psCompressed, // stream pointer
									m_nTimeFrame, // time of this frame
									1, // number to write
									m_pImageBuffer,
									HV_Width * HV_Height * 3, // lpbi->biSizeImage, // size of this frame
									AVIIF_KEYFRAME, // flags....
									NULL,
									NULL
									);
		if (hr == AVIERR_OK){
			m_nTimeFrame++;
		}
	}

	return 1;
}

//-----------------------------------------------------------------------------

//根据卡的其他参数设置曝光时间
//其他的参数如摄像机时钟频率,消隐值都取默认值,
//参数:
//nWindWidth:当前图像宽度
//lTintUpper:曝光时间的分子, lTintUpper/lTintLower 组成实际的曝光时间
//lTintLower:曝光时间的分母,lTintUpper/lTintLower 组成实际的曝光时间
void TMainFrm::SetExposureTime(int nWindWidth,long lTintUpper,long lTintLower)
{
	int size = sizeof(HVTYPE);
	HVTYPE type;
	HVGetDeviceInfo(m_hhv,DESC_DEVICE_TYPE, &type, &size);	
	
	//When outputwindow changes, change the exposure 
	//请参考曝光系数转换公式
	long lClockFreq = 24000000; 
	int nOutputWid = nWindWidth;
	double dExposure = 0.0;
	double dTint = max((double)lTintUpper/(double)lTintLower,MY_ZERO);
	if(type == HV1300UCTYPE || type == HV1301UCTYPE)	
	{
		long lTb = 0;
		dExposure = (dTint* lClockFreq + 180.0)/((double)nOutputWid + 244.0 + lTb);
	}
	else
	{		
		long lTb = 0;
		dExposure = (dTint* lClockFreq + 180.0)/((double)nOutputWid + 305.0 + lTb)  + 1 ;
	}
	
	if (dExposure > 16383) 
		dExposure = 16383;
	HVAECControl(m_hhv, AEC_EXPOSURE_TIME, (long)dExposure);
	
}

⌨️ 快捷键说明

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