- 最近开发一个项目,用映美精相机配合halcon做取图开发,由于网上资料小特意写个记录。
- 到映美精官网下载驱动,映美精官网,下载映美精的工具开发包SDK 映美精的SDK
- 下载SDK后找到classlib文件夹
里面就是SDK - 新建一个qt程序,引入SDK
- 新建一个相机类
头文件
cpp
#ifndef CAMERAGRAP_H
#define CAMERAGRAP_H
#include <QObject>
#include "QDebug"
#include <tisudshl.h>
#include <algorithm>
/***sink监控***/
class SinkListener : public DShowLib::FrameQueueSinkListener
{
public:
/***槽链接成功***/
void sinkConnected(DShowLib::FrameQueueSink& sink,
const DShowLib::FrameTypeInfo& frameType );
/***取到图片是响应***/
void framesQueued( DShowLib::FrameQueueSink& sink );
/***槽链接断开回调***/
void sinkDisconnected(DShowLib::FrameQueueSink& sink );
};
class CameraGrap : public QObject
{
Q_OBJECT
public:
explicit CameraGrap(QObject *parent = nullptr);
~CameraGrap();
/***初始化***/
void Init();
/***读取配置***/
void ReadConfig();
/***保存配置***/
bool WriteConfig();
/***开始相机***/
void StartCamera();
/***停止相机***/
void StopCamera();
/***释放资源***/
void ReleaseSource();
/***设置相机的触发模式为触发取图***/
void SetCameraTriggerTakeImage();
/***设置相机试试视频取图***/
void SetCameraLiveTakeImage();
/***设置相机曝光***/
void SetCameraExpource(double expource_);
/***设置相机增益***/
void SetCameraGain(double gain_);
/***触发下相机取图***/
void TriggerCameraTakeImage();
// /***槽链接成功***/
// void sinkConnected(DShowLib::FrameQueueSink& sink,
// const DShowLib::FrameTypeInfo& frameType );
// /***取到图片是响应***/
// void framesQueued( DShowLib::FrameQueueSink& sink );
// /***槽链接断开回调***/
// void sinkDisconnected(DShowLib::FrameQueueSink& sink );
// /***重写取图回调函数***/
// void frameReady(DShowLib::Grabber& caller, smart_ptr<DShowLib::MemBuffer> pBuffer, DWORD FrameNumber ) override;
// void overlayCallback(DShowLib::Grabber& caller, smart_ptr<DShowLib::OverlayBitmap> pBitmap, const DShowLib::tsMediaSampleDesc& desc );
signals:
// /***获取图片完成标志***/
// void FinallyGetImage();
public:
static CameraGrap _camer_grap;
/***相机名称***/
QString _camera_name;
/***相机视频的格式***/
QString _camera_video_format;
/***相机曝光***/
double _camera_expource;
/***相机增益***/
double _camera_gain;
/***相机抗干扰数***/
double _camera_noise_suppression;
/***相机有无标志***/
bool _camera_exist;
/***创建一个抓拍,一定创建成指针形式,不然会跟***/
DShowLib::Grabber* _grabber;
// /***sink监控***/
SinkListener _listener_instance;
// DShowLib::FrameTypeInfoArray _accepted_types;
/***接受图片的格式***/
DShowLib::FrameTypeInfo _accepted_type;
/***槽***/
DShowLib::tFrameQueueSinkPtr _psink;
};
#endif // CAMERAGRAP_H
内容文件
cpp
#include "cameragrap.h"
#include <DeeplearnInspection/deeplearninspection.h>
#include <QCoreApplication>
#include "xlsxdocument.h"
#include "QMetaMethod"
// #include "ic4-interop/interop-HALCON.h"
CameraGrap CameraGrap::_camer_grap;
void SinkListener::sinkConnected(DShowLib::FrameQueueSink& sink,
const DShowLib::FrameTypeInfo& frameType )
{
UNREFERENCED_PARAMETER( frameType );
/***链接成功分配内存***/
sink.allocAndQueueBuffers(1);
}
void SinkListener::framesQueued(DShowLib::FrameQueueSink& sink)
{
DShowLib::tFrameQueueBufferPtr buffer = sink.popOutputQueueBuffer();
//unsigned int frame_number = buffer->getFrameMetaData().mediaSampleDesc.FrameNumber;
// DShowLib::tColorformatEnum format_= buffer->getFrameType().getColorformat();
int width_=buffer->getFrameType().dim.cx;
int height_=buffer->getFrameType().dim.cy;
// HalconCpp::GenImageInterleaved(&ho_Image, (void*)pBuffer, "rgb", width, height, 0, "byte", width * 3, height, 0, 0);
HalconCpp::HTuple hptr_=(Hlong)buffer->getPtr();
HalconCpp::GenImage1(&DeeplearnInspection::_deeplearn_inspection._image,
"byte",
width_,
height_,
hptr_);
DeeplearnInspection::_deeplearn_inspection._image_exist=true;
hptr_.Clear();
/***释放内存资源***/
buffer.destroy();
int size_input_= sink.getInputQueueSize();
int size_output_=sink.getOutputQueueSize();
sink.popAllOutputQueueBuffers().clear();
sink.popAllInputQueueBuffers().clear();
/***重新分配内存资源***/
sink.allocAndQueueBuffers(1);
size_input_= sink.getInputQueueSize();
size_output_=sink.getOutputQueueSize();
/***触发相机取图完成***/
DeeplearnInspection::_deeplearn_inspection.TriggerCameraImageWriteFinally();
}
void SinkListener::sinkDisconnected(DShowLib::FrameQueueSink& sink)
{
;
}
CameraGrap::CameraGrap(QObject *parent)
: QObject{parent}
{
}
CameraGrap::~CameraGrap()
{
}
void CameraGrap::Init()
{
/***读取配置***/
ReadConfig();
/***初始化相机底层***/
DShowLib::InitLibrary();
/***创建一个抓拍***/
_grabber=new DShowLib::Grabber();
/***获取相机驱动***/
auto cameras_= _grabber->getAvailableVideoCaptureDevices();
/***判断有没有相机***/
int camera_count_= cameras_->size();
if(camera_count_>0)
{
for(int i=0;i<camera_count_;i++)
{
/***获取相机名称***/
std::string camera_name_;
camera_name_=cameras_->at(i).getName();
if(camera_name_==_camera_name.toStdString())
{
i=camera_count_;
if(_grabber->openDev(camera_name_))
{
//_grabber->showVCDPropertyPage();
/***设置图片格式***/
// _grabber->setVideoFormat("Y800 (1424x712)");
DShowLib::dstringa video_format_=_camera_video_format.toStdString();
_grabber->setVideoFormat(video_format_);
/***设置外部出发***/
_grabber->setExternalTrigger(1);
/***给如抗误触发参数***/
DShowLib::tIVCDAbsoluteValuePropertyPtr noise_suppression_time_ = _grabber->getVCDPropertyInterface<DShowLib::IVCDAbsoluteValueProperty>(DShowLib::VCDID_Trigger, DShowLib::VCDElement_TriggerNoiseSuppressionTime);
if(noise_suppression_time_==NULL)
{
qDebug() << "noise suppression time auto is failed";
}
else
{
long max_=noise_suppression_time_->getRangeMax();
long min_=noise_suppression_time_->getRangeMin();
long cvalue_;
cvalue_=noise_suppression_time_->getValue();
qDebug() << "noise suppression time is "+QString::number(cvalue_);
if((max_>=_camera_noise_suppression)
&&(min_<=_camera_noise_suppression))
{
noise_suppression_time_->setValue(_camera_noise_suppression);
}
else
{
noise_suppression_time_->setValue(min_);
}
}
/***设置帧率***/
_grabber->setFPS(120);
// Enable the overlay bitmap to display the frame counter in the live video.
_grabber->setOverlayBitmapPathPosition( DShowLib::ePP_DEVICE );
_grabber->getOverlay(DShowLib::ePP_DEVICE )->setEnable( true );
// Create a FrameTypeInfoArray data structure describing the allowed color formats.
//_accepted_types= DShowLib::FrameTypeInfoArray::createStandardTypesArray();
/***设置槽接受图片的格式***/
_accepted_type =DShowLib::eY800;
// Create the frame sink
_psink= DShowLib::FrameQueueSink::create(this->_listener_instance, _accepted_type);
// Apply the sink to the grabber.
_grabber->setSinkType(_psink);
/***设置曝光手动***/
DShowLib::tIVCDSwitchPropertyPtr exposure_auto = _grabber->getVCDPropertyInterface<DShowLib::IVCDSwitchProperty>( DShowLib::VCDID_Exposure, DShowLib::VCDElement_Auto);
if( exposure_auto == NULL )
{
qDebug() << "exposure auto is failed";
}
else
{
exposure_auto->setSwitch(false);
}
/***获取曝光的范围,设置相机曝光***/
DShowLib::tIVCDRangePropertyPtr exposure_range = _grabber->getVCDPropertyInterface<DShowLib::IVCDRangeProperty>(DShowLib::VCDID_Exposure, DShowLib::VCDElement_Value);
if( exposure_range == NULL )
{
qDebug() << "exposure auto is failed";
}
else
{
// std::cout << "Current Exposure range value: " << exposure_range->getValue() << std::endl;
// std::cout << "Exposure range range: [" << exposure_range->getRangeMin() << ".." << exposure_range->getRangeMax() << "]" << std::endl;
long max_=exposure_range->getRangeMax();
long min_=exposure_range->getRangeMin();
long cvalue_;
cvalue_=exposure_range->getValue();
qDebug() << "expource is "+QString::number(cvalue_);
if((max_>=_camera_expource)
&&(min_<=_camera_expource))
{
exposure_range->setValue(_camera_expource);
}
else
{
exposure_range->setValue(min_);
}
}
// /***确认曝光是否设置成功***/
// DShowLib::tIVCDAbsoluteValuePropertyPtr exposure_absolute = _grabber.getVCDPropertyInterface<DShowLib::IVCDAbsoluteValueProperty>( DShowLib::VCDID_Exposure,DShowLib::VCDElement_Value);
// if( exposure_absolute == NULL )
// {
// qDebug() << "vilation is failed";
// }
// else
// {
// long exposure_= exposure_absolute->getValue();
// qDebug() << "expource is "+QString::number(exposure_);
// }
/***设置增益手动***/
DShowLib::tIVCDSwitchPropertyPtr gain_auto = _grabber->getVCDPropertyInterface<DShowLib::IVCDSwitchProperty>( DShowLib::VCDID_Gain, DShowLib::VCDElement_Auto);
if( gain_auto == NULL )
{
qDebug() << "exposure auto is failed";
}
else
{
gain_auto->setSwitch(false);
}
/***获取增益范围,设置增益***/
DShowLib::tIVCDRangePropertyPtr gain_range = _grabber->getVCDPropertyInterface<DShowLib::IVCDRangeProperty>(DShowLib::VCDID_Gain, DShowLib::VCDElement_Value);
if( gain_range == NULL )
{
qDebug() << "exposure auto is failed";
}
else
{
long max_=gain_range->getRangeMax();
long min_=gain_range->getRangeMin();
long cvalue_;
cvalue_=gain_range->getValue();
if((max_>=_camera_gain)
&&(min_<=_camera_gain))
{
gain_range->setValue(_camera_gain);
}
else
{
gain_range->setValue(min_);
}
}
// /***确认曝光是否设置成功***/
// DShowLib::tIVCDAbsoluteValuePropertyPtr gain_absolute = _grabber.getVCDPropertyInterface<DShowLib::IVCDAbsoluteValueProperty>( DShowLib::VCDID_Gain,DShowLib::VCDElement_Value);
// if( gain_absolute == NULL )
// {
// qDebug() << "vilation is failed";
// }
// else
// {
// long gain_= gain_absolute->getValue();
// qDebug() << "gain is "+QString::number(gain_);
// }
_camera_exist=true;
}
}
}
}
else
{
_camera_exist=false;
qDebug() << "no found devices";
}
}
void CameraGrap::ReadConfig()
{
QString config_path_=QCoreApplication::applicationDirPath()+"/CameraConfig.xlsx";
QFile file_(config_path_);
if(file_.exists())
{
QXlsx::Document xlsx_(config_path_);
if(xlsx_.load())
{
int row_count_=xlsx_.dimension().rowCount();
int column_count_=xlsx_.dimension().columnCount();
if((row_count_>4)
&&(column_count_>1))
{
_camera_name= xlsx_.cellAt(2,2)->value().toString();
_camera_expource=xlsx_.cellAt(3,2)->value().toDouble();
_camera_gain=xlsx_.cellAt(4,2)->value().toDouble();
_camera_video_format=xlsx_.cellAt(5,2)->value().toString();
_camera_noise_suppression=xlsx_.cellAt(6,2)->value().toDouble();
}
else
{
qDebug() << "Failed to load CameraConfig.xlsx file.";
}
}
}
else
{
qDebug() << "CameraConfig.xlsx file is not exist";
}
file_.close();
}
bool CameraGrap::WriteConfig()
{
bool ok_=false;
QString config_path_=QCoreApplication::applicationDirPath()+"/CameraConfig.xlsx";
QXlsx::Document xlsx_;
/***写入抬头***/
xlsx_.write(1,1,"名称");
xlsx_.write(1,2,"值");
xlsx_.write(2,1,"CameraName");
xlsx_.write(2,2,_camera_name);
xlsx_.write(3,1,"Expource");
xlsx_.write(3,2,QString::number(_camera_expource));
xlsx_.write(4,1,"Gain");
xlsx_.write(4,2,QString::number(_camera_gain));
xlsx_.write(5,1,"VideoFormat");
xlsx_.write(5,2,_camera_video_format);
xlsx_.write(6,1,"NoiseSuppression");
xlsx_.write(6,2,_camera_noise_suppression);
if(!xlsx_.saveAs(config_path_))
{
qDebug() << "save the DataCache.xlsx failed";
}
else
{
ok_=true;
}
return ok_;
}
void CameraGrap::StartCamera()
{
if(_camera_exist==true)
{
_grabber->startLive(false);
}
}
void CameraGrap::StopCamera()
{
if(_camera_exist==true)
{
_grabber->stopLive();
}
}
void CameraGrap::ReleaseSource()
{
if(_camera_exist==true)
{
if (_grabber->isDevOpen())
{
if(_grabber->isLive())
{
_grabber->stopLive();
}
_grabber->closeDev();
}
}
delete _grabber;
}
void CameraGrap::SetCameraTriggerTakeImage()
{
if(_camera_exist==true)
{
/***设置触发模式为软触发***/
_grabber->setExternalTrigger(true);
}
}
void CameraGrap::SetCameraLiveTakeImage()
{
if(_camera_exist==true)
{
/***设置相机直播模式***/
_grabber->setExternalTrigger(false);
}
}
void CameraGrap::SetCameraExpource(double expource_)
{
if(_camera_exist==true)
{
_camera_expource =expource_;
/***获取曝光的范围,设置相机曝光***/
DShowLib::tIVCDRangePropertyPtr exposure_range = _grabber->getVCDPropertyInterface<DShowLib::IVCDRangeProperty>(DShowLib::VCDID_Exposure, DShowLib::VCDElement_Value);
if( exposure_range == NULL )
{
qDebug() << "exposure auto is failed";
}
else
{
// std::cout << "Current Exposure range value: " << exposure_range->getValue() << std::endl;
// std::cout << "Exposure range range: [" << exposure_range->getRangeMin() << ".." << exposure_range->getRangeMax() << "]" << std::endl;
long max_=exposure_range->getRangeMax();
long min_=exposure_range->getRangeMin();
long cvalue_;
cvalue_=exposure_range->getValue();
qDebug() << "expource is "+QString::number(cvalue_);
if((max_>_camera_expource)
&&(min_<_camera_expource))
{
exposure_range->setValue(_camera_expource);
}
else
{
exposure_range->setValue(min_);
}
}
}
}
void CameraGrap::SetCameraGain(double gain_)
{
if(_camera_exist==true)
{
_camera_gain=gain_;
DShowLib::tIVCDRangePropertyPtr gain_range = _grabber->getVCDPropertyInterface<DShowLib::IVCDRangeProperty>(DShowLib::VCDID_Gain, DShowLib::VCDElement_Value);
if( gain_range == NULL )
{
qDebug() << "exposure auto is failed";
}
else
{
long max_=gain_range->getRangeMax();
long min_=gain_range->getRangeMin();
long cvalue_;
cvalue_=gain_range->getValue();
if((max_>_camera_gain)
&&(min_<_camera_gain))
{
gain_range->setValue(_camera_gain);
}
else
{
gain_range->setValue(min_);
}
}
}
}
void CameraGrap::TriggerCameraTakeImage()
{
if(_camera_exist==true)
{
DShowLib::tIVCDButtonPropertyPtr btn_= _grabber->getVCDPropertyInterface<DShowLib::IVCDButtonProperty>(DShowLib::VCDID_TriggerMode, DShowLib::VCDElement_SoftwareTrigger);
if(btn_==NULL)
{
}
else
{
btn_->push();
}
}
}
// void CameraGrap::frameReady(DShowLib::Grabber& caller,smart_ptr<DShowLib::MemBuffer> pBuffer,DWORD FrameNumber)
// {
// // int width_=pBuffer->getFrameType().dim.cx;
// // int height_=pBuffer->getFrameType().dim.cy;
// // uchar* ptr_=static_cast<uchar*>(pBuffer->getPtr());
// // HalconCpp::HTuple hptr_=(int)ptr_;
// // HalconCpp::GenImage1(&DeeplearnInspection::_deeplearn_inspection._image,
// // "byte",
// // width_,
// // height_,
// // hptr_);
// // hptr_.Clear();
// // QMetaMethod value_change_signal_=QMetaMethod::fromSignal(&CameraGrap::FinallyGetImage);
// // if(this->isSignalConnected(value_change_signal_))
// // {
// // emit FinallyGetImage();
// // }
// ;
// }
// void CameraGrap::overlayCallback(DShowLib::Grabber& caller,
// smart_ptr<DShowLib::OverlayBitmap> pBitmap,
// const DShowLib::tsMediaSampleDesc& desc)
// {
// }
6.代码分析
要获取相机的图片,主要创建一个类继承public DShowLib::FrameQueueSinkListener,
然后设置sink,代码如下:
// Create the frame sink
_psink= DShowLib::FrameQueueSink::create(this->_listener_instance, _accepted_type);
// Apply the sink to the grabber.
_grabber->setSinkType(_psink);
在相机取到图片后会回调sink,即回调framesQueued函数,在里面进行转换。