HV_Camera::~HV_Camera() { // 停止采集图像到内存,可以再次调用HVStartSnapEx启动数字摄像机采集 HVSTATUS status =STATUS_OK; status = HVStopSnap(m_hhv); HV_VERIFY(status); // 终止数字摄像机采集图像到内存,同时释放所有采集环境, // 再次启动数字摄像机采集,必须重新初始化 status = STATUS_OK; status = HVCloseSnap(m_hhv); HV_VERIFY(status); // 关闭设备 status = STATUS_OK; EndHVDevice(m_hhv); //关闭设备 HV_VERIFY(status); delete m_pRawBuffer; delete m_pImageBuffer; };
CMainFrame::CMainFrame() { // TODO: add member initialization code here //InitConsole() ; /* * 初始化所有成员变量,同时打开数字摄像机 */ HVSTATUS status = STATUS_OK; m_bStart = FALSE; m_pBmpInfo = NULL; m_pRawBuffer = NULL; m_pImageBuffer = NULL; DisplayBuffer = NULL; for(int i=0;i<256;i++) { m_pLutR[i] = i; m_pLutG[i] = i; m_pLutB[i] = i; } // 打开数字摄像机 1 status = BeginHVDevice(1, &m_hhv); // 检验函数执行状态,如果失败,则返回错误状态消息框 HV_VERIFY(status); }
IplImage* HV_Camera::HV_QueryFrame() { IplImage* Pimage; HVSTATUS status = STATUS_OK; CString strMsg; //只定义一个缓冲区来保存图象数据 BYTE *ppBuf[1]; ppBuf[0] = m_pRawBuffer; status = HVSnapShot(m_hhv, ppBuf, 1); if (STATUS_OK < status || status < STATUS_INTERNAL_ERROR) { CString str=""; str.Format("Error : 0x%08x",status); ::MessageBox(NULL, str , "Error", MB_ICONWARNING | MB_OK); }else{ HV_VERIFY(status); } // 将原始图像数据进行Bayer转换,转换后为24位。 //同时将原始数据进行上下翻转 ConvertBayer2Rgb(m_pImageBuffer,m_pRawBuffer,Width,Height,ConvertType, m_pLutR,m_pLutG,m_pLutB,true,m_Layout); Pimage = Byte2IplImg(m_pImageBuffer, Width ,Height ); return Pimage; }
void CMainFrame::OnSnapexStop() { // TODO: Add your command handler code here HVSTATUS status =STATUS_OK; // 停止采集图像到内存,可以再次调用HVStartSnapEx启动数字摄像机采集 status = HVStopSnap(m_hhv); HV_VERIFY(status); if (HV_SUCCESS(status)) { m_bStart = FALSE; } }
void CMainFrame::OnSnapexOpen() { // TODO: Add your command handler code here HVSTATUS status = STATUS_OK; /* * 初始化数字摄像机采集图像到内存的控制, * 指定回调函数SnapThreadCallback和用户参数m_hWnd */ status = HVOpenSnap(m_hhv, SnapThreadCallback, m_hWnd); HV_VERIFY(status); }
int HV_Camera::CameraCount() { int nDeviceCount = 0; //设备总数变量 HVSTATUS status = HVGetDeviceTotal(&nDeviceCount); HV_VERIFY(status); return nDeviceCount; }
CMainFrame::~CMainFrame() { HVSTATUS status = STATUS_OK; // 关闭数字摄像机,释放数字摄像机内部资源 status = EndHVDevice(m_hhv); HV_VERIFY(status); // 回收图像缓冲区 delete []m_pRawBuffer; delete []m_pImageBuffer; delete []DisplayBuffer; }
HVSTATUS HV_Camera::HVregister(HV_SNAP_PROC pSnapFunc,void *pParam) { HVSTATUS status = STATUS_OK; /* * 初始化数字摄像机采集图像到内存的控制, * 指定回调函数SnapThreadCallback和this指针 */ status = HVOpenSnap(m_hhv, pSnapFunc,pParam); HV_VERIFY(status); status = STATUS_OK; /* * 启动数字摄像机采集图像到内存 */ BYTE *ppBuf[1]; ppBuf[0] = m_pRawBuffer; status = HVStartSnap(m_hhv, ppBuf,1); HV_VERIFY(status); return status; }
void CMainFrame::OnSnapexClose() { // TODO: Add your command handler code here HVSTATUS status = STATUS_OK; /* * 终止数字摄像机采集图像到内存,同时释放所有采集环境, * 再次启动数字摄像机采集,必须重新初始化 */ status = HVCloseSnap(m_hhv); HV_VERIFY(status); if (HV_SUCCESS(status)) { m_bOpen = FALSE; m_bStart = FALSE; } }
void CMainFrame::OnSnapexStart() { // TODO: Add your command handler code here HVSTATUS status = STATUS_OK; /* * 启动数字摄像机采集图像到内存 */ BYTE *ppBuf[1]; ppBuf[0] = m_pRawBuffer; status = HVStartSnap(m_hhv, ppBuf,1); HV_VERIFY(status); if (HV_SUCCESS(status)) { m_bStart = TRUE; } }
void CMainFrame::Scan() { CView *pView = GetActiveView(); //获取当前VIEW视图 CDC *pDC = pView->GetDC(); //得到VIEW的DC CString cs; cs.Format("%d",Scan_num+1); pDC->TextOut(0,Height/2,cs,cs.GetLength()); pView->ReleaseDC(pDC); int i,k; unsigned char MAX=0; int MAX_i=0; unsigned char seq[3]; float peak; float distance; float Phi; //float Theta; float Z; float L1,L2,L3,L4; float r; uchar* ptr; HVSTATUS status =STATUS_OK; /********采集单帧图像**********/ unsigned char *ppbuffer[1]; ppbuffer[0]=m_pRawBuffer; status =HVSnapShot(m_hhv,ppbuffer,1); HV_VERIFY(status); /********显示当前帧************/ OnSnapChange(NULL,NULL); //生成支持OPENCV的IPLIMAGE数据结构,并使用相机采集的图像数据初始化// CvSize cvSize; cvSize.width = Width; cvSize.height = Height; IplImage *iplImage = cvCreateImageHeader(cvSize,IPL_DEPTH_8U,3); cvSetData(iplImage,m_pImageBuffer,Width*3); //申请灰度空间,将BGR格式转化为灰度数据 IplImage *iplgray = cvCreateImage(cvGetSize(iplImage),IPL_DEPTH_8U,1); cvCvtColor(iplImage,iplgray,CV_BGR2GRAY); for(k=0;k<Height;k++) { ptr=(uchar*)(iplgray->imageData+k*iplgray->widthStep); for(i=0;i<Width;i++) for(i=0;i<Width;i++) { if( ptr[i]>=MAX) { MAX=ptr[i]; MAX_i=i; } } if(MAX<=50) { Scan_result[Scan_num][k].X=0; Scan_result[Scan_num][k].Y=0; Scan_result[Scan_num][k].Z=0; continue; } if(MAX_i<=1) seq[2]=0; else seq[2]=ptr[MAX_i-1]; seq[1]=ptr[MAX_i]; if(MAX_i>=Width) seq[0]=0; else seq[0]=ptr[MAX_i+1]; //peak=1/2*(log(seq[0])-log(seq[2]))/(log(seq[0])-2*log(seq[1])+log(seq[2]))+Width-MAX_i; peak=(seq[2]-seq[0])/(seq[0]+seq[1]+seq[2])+Width-MAX_i; //peak=(2*ptr[MAX_i-2]+ptr[MAX_i-1]-ptr[MAX_i+1]-2*ptr[MAX_i+2])/(ptr[MAX_i+2]+ptr[MAX_i+1]+ptr[MAX_i]+ptr[MAX_i-1]+ptr[MAX_i-2])+Width-MAX_i; /************************计算某行扫描结果*****************************************/ distance=FS/(PIX_SIZE*peak+ PIX_OFF)+DIST_OFF; if(distance>1800) { Scan_result[Scan_num][k].X=0; Scan_result[Scan_num][k].Y=0; Scan_result[Scan_num][k].Z=0; continue; } //Theta=atan((k-Height/2)*PIX_SIZE/f); Z=(distance-DIST_OFF)*(Height/2-k)*PIX_SIZE/f; L1=sqrt(distance*distance+Z*Z); L3= distance*tan(PI/2- LaserAngle); L2= sqrt(L1*L1+L3*L3); L4= sqrt(L3*L3+distance*distance); r= sqrt( (L3-rotation_r)*(L3-rotation_r)+distance*distance); Phi=Scan_num*Scan_step+PI/2-acos( (rotation_r*rotation_r+r*r-L4*L4)/2.0f/rotation_r/r); Scan_result[Scan_num][k].X=r*cos(Phi); Scan_result[Scan_num][k].Y=r*sin(Phi); Scan_result[Scan_num][k].Z=Z; /****************************************************************************/ } cvReleaseImage(&iplgray); /************如果扫描完成,关闭串口,并输出数据********/ if(Scan_num==Scan_total-1) { MessageBox("扫描完成"); Scan_num=0; OnBtnSend('2'); //OnBtnSend('2'); sio_close(Port); //关闭串口 /*************数据输出**************/ char* fileName=dataout; CString strtemp; CFile file; CFileException fileException; if(!file.Open(fileName,CFile::modeCreate | CFile::modeWrite, &fileException)) { CString errorInfo; errorInfo.Format("不能打开文件%s,错误:%u\n",fileName,fileException.m_cause); MessageBox(errorInfo,"错误",MB_OK|MB_ICONERROR); return; } for(i=0;i<Scan_total;i++) for(k=0;k<Height;k++) { if(Scan_result[i][k].X==0 & Scan_result[i][k].Y==0 & Scan_result[i][k].Z==0) continue; else { strtemp.Format("%.3f, %.3f, %.3f\r\n\r\n",Scan_result[i][k].X,Scan_result[i][k].Y,Scan_result[i][k].Z); file.Write(strtemp,strtemp.GetLength()); } } file.Close(); MessageBox("已成功输出数据","信息",MB_OK|MB_ICONINFORMATION); return; } /**********扫描未完成,发送串口指令***********/ else { OnBtnSend('1'); //OnBtnSend('1'); Scan_num=Scan_num+1; } }
void HV_Camera::InitCamera() { HVSTATUS status = BeginHVDevice(DeviceId, &m_hhv);// 打开数字摄像机 1 HV_VERIFY(status); // 检验函数执行状态,如果失败,则返回错误状态消息框 m_Layout = HVGetBayerType(); /************************************************************* 初始化数字摄像机硬件状态,用户也可以在其他位置初始化数字摄像机, 但应保证数字摄像机已经打开,建议用户在应用程序初始化时, 同时初始化数字摄像机硬件。 *************************************************************/ HVSetResolution(m_hhv, Resolution); //设置数字摄像机分辨率 HVSetSnapMode(m_hhv, SnapMode); //采集模式,包括 CONTINUATION(连续)、TRIGGER(外触发) for (int i = 0; i < 4; i++){ //设置各个分量的增益 HVAGCControl(m_hhv, RED_CHANNEL + i, Gain); } HVADCControl(m_hhv, ADC_BITS, ADCLevel); //设置ADC的级别 HVTYPE type = UNKNOWN_TYPE; //获取设备类型 int size = sizeof(HVTYPE); HVGetDeviceInfo(m_hhv,DESC_DEVICE_TYPE, &type, &size); // 设置图像窗口和消隐前,首先查看是否满足特殊相机的条件限制? /***************************************************************************/ if (IS_USB_GV400(type)) { int rate = 0; switch(Resolution) { case RES_MODE0: rate = 1; break; case RES_MODE1: rate = 2; break; default: break; } //GV400Ux相机要求图像宽度和水平消隐满足以下公式: //lHBlanking + Width*rate > 0x236 //如果不满足上述条件,需要用户做出调整,增大图像宽度或增大水平消隐 if (m_lHBlanking + Width*rate <= 0x236) { //取得消隐的边界值 DWORD pBlankSize[4]; int nBufSize = 0; int nHmin = 0; int nHmax = 0; HVGetDeviceInfo(m_hhv,DESC_DEVICE_BLANKSIZE,NULL,&nBufSize); HVGetDeviceInfo(m_hhv,DESC_DEVICE_BLANKSIZE,pBlankSize,&nBufSize); nHmin = (int)pBlankSize[0]; nHmax = (int)pBlankSize[2]; int tHor = 0x236-Width*rate+1; //获取此图像宽度下允许的水平消隐最小值 m_lHBlanking = max(nHmin,min(tHor, nHmax)); } //为防止消隐设置不成功先将图像窗口设为最大 int nBuffSize = 0; HVGetDeviceInfo(m_hhv, DESC_RESOLUTION, NULL,&nBuffSize); BYTE *pbContext = new BYTE[nBuffSize]; DWORD *pdContext = (DWORD *)(pbContext); HVGetDeviceInfo(m_hhv, DESC_RESOLUTION, pdContext,&nBuffSize); int nMaxWid = *(pdContext + 2*Resolution); int nMaxHei = *(pdContext + 2*Resolution +1); delete []pbContext; HVSetOutputWindow(m_hhv, 0, 0, nMaxWid, nMaxHei); //设置消隐。 HVSetBlanking(m_hhv, m_lHBlanking, m_lVBlanking); } else { //设置消隐。 HVSetBlanking(m_hhv, m_lHBlanking, m_lVBlanking); } /***************************************************************************/ /************************************************************************ 视频输出窗口,即视频输出范围,输出窗口取值范围必须在输入窗口范围以内, 视频窗口左上角X坐标和窗口宽度应为4的倍数,左上角Y坐标和窗口高度应为2的倍数 输出窗口的起始位置一般设置为(0, 0)即可。 *************************************************************************/ HVSetOutputWindow(m_hhv, XStart, YStart, Width, Height); HVSetSnapSpeed(m_hhv, SnapSpeed); //设置采集速度 SetExposureTime(Width, ExposureTint_Upper, ExposureTint_Lower, // 设置曝光时间 m_lHBlanking, SnapSpeed, Resolution); m_pBmpInfo = (BITMAPINFO *)m_chBmpBuf;// m_pBmpInfo即指向m_chBmpBuf缓冲区,用户可以自己分配BTIMAPINFO缓冲区 m_pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);// 初始化BITMAPINFO 结构,此结构在保存bmp文件、显示采集图像时使用 m_pBmpInfo->bmiHeader.biWidth = Width; // 图像宽度,一般为输出窗口宽度 m_pBmpInfo->bmiHeader.biHeight = 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[Width * Height]; ASSERT(m_pRawBuffer); /*********************************************** 分配Bayer转换后图像数据缓冲 ************************************************/ m_pImageBuffer = new BYTE[Width * Height*3]; ASSERT(m_pImageBuffer); }