激光三角相机开发
前几天刚完成的线激光三角相机开发,简单实现了简单的线扫功能。
总结
使用鲍威尔激光头(号称是可以产生极细激光线,结果感觉效果和40左右的激光没啥区别,凑合用吧),海康30万像素相机(取像满帧率200),镜头25mm,标定使用halcon标定,计算用c++,标定完成后不依赖halcon可直接运行。
生成单条纹点云图如下:
以下将通过取像,标定,查找激光线,计算单点四步进行讲解:
取像
刚开用了延时取像,结果抓取图像速度太慢(12ms一张图),使用回调函数取像正常帧率。但是这里就有了一个疑问,如果将回调函数封装成dll,当想要修改回调函数中数据处理过程时岂不是都要改源码?有没有很好一种方式,能有利于开发者直接修改回调函数中的程序,编程小白请求答疑。
标定
halcon标定:
1、标定相机内外参数
2、标定光平面
查找激光线
在找激光线的过程中仅使用了阈值分割,遍历每个像素值,找到图像每列上的像素点,未使用滤波、剔除异常点、膨胀等图形处理操作。
计算单点
通过内参校正当前像素点的畸变,通过外参找到此点在空间中的位置,通过投影得到世界坐标系中的位置,根据世界坐标系与光平面关系求得在光平面坐标系中的位置,输出结果,得到输出的点云图。
2020.7.30更新
留了个坑,来填一下,经过研究发现,海康sdk自带回调函数,但是不能讲这个函数封装到类中,因此我想了其他方法,就是自己定义一个函数指针在相机类中,类外通过回调函数调用这个指针即可,贴一段代码。
//类外
typedef void (*ProcessCallback)(unsigned char*); //定义函数指针类型
ProcessCallback pProcessCallback = NULL; //初始化一个指针,做为桥梁接连回调函数和类中的回调函数
//海康相机提供的原始回调函数
void __stdcall ImageCallBackEx(unsigned char * pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser)
{
if (pFrameInfo)
{
pProcessCallback(pData);
}
}
//类内部,
//首先定义外接接口和标志
bool bCallBack; // 是否注册回调函数,默认false
ProcessCallback pUserProcessCallback = NULL; // 类中函数指针实例,供外部调用。回调需赋值,记得初始化
//由于海康sdk在开始取流前需要配置回调,
//因此MV_CC_StartGrabbing(hDeviceHandle)这段代码要放在如下代码后,
//否则无法生效。
if (bCallBack)
{
if (NULL == pUserProcessCallback)
{
printf("没有回调,记得关闭相机 \r\n");
}
pProcessCallback = pUserProcessCallback;
// ch:注册抓图回调 | en:Register image callback
nRet = MV_CC_RegisterImageCallBackEx(hDeviceHandle, ImageCallBackEx, hDeviceHandle);
}
不过因为更新了数据结构,新增图像矩阵类,并实现泛型,因此也加上了膨胀操作,虽然改了上面的取像方式但是还是一如既往的慢。。