基于机器视觉的高速在线药粒计数系统程序的设计
2023-10-16孙凯明
孙凯明,郝 明,王 刚
(黑龙江省科学院智能制造研究所,哈尔滨 150090)
0 引言
中药丸的分拣包装主要采用常工计数法[1]、机械计数法[2]、光电数粒机[3]等,这些方法计数速度慢,设备占地面积大,只能针对特定规格的中药丸进行计数分装。随着视觉检测技术的发展,视觉数粒技术在药片包装中的应用得到广泛研究。姚莹[4]等研制了一种平板式数粒机,通过机器视觉系统及药粒位置分析实现药粒的快速准确计数。DATA公司研制了ICU系列—基于机器视觉的高速药粒数粒装瓶机,其结构紧凑,计数准确。但机器视觉计数容易受到外界条件的干扰,在我国药厂难以普及,故研究基于机器视觉且计数精准的高速药粒计数系统具有广阔的市场前景。针对基于机器视觉的高速在线药粒计数系统方案,结合Dalsa线阵相机SDK、Opencv 4.55及Visual Studio 2019,设计了基于机器视觉的高速在线药粒计数系统程序。
1 硬件设计
基于机器视觉的高速在线药粒计数系统由线阵相机、振动盘、光源及PLC控制器组成(如图1所示)。药粒高速下落时可能发生碰撞等情况,轨迹变得不规则,通过线阵相机成像后,颗粒间的位置关系不再发生改变,可利用药粒间的位置关系信息去除重复计数的药粒,实现精准计数。本系统选择DALSA的LA-GM-04K08A-00-R型号线阵相机,为减小运动模糊,摄像机的曝光时间很短,需要使用高强度的光源才能产生足够的光通量,故采用面光源背向照明的方式,以突出其轮廓特征。
图1 基于机器视觉的高速在线药粒计数系统Fig.1 High-speed on-line drug counting system based on machine vision
2 程序设计
2.1 线阵相机图像采集及处理程序设计
图像采集事件处理类用于显示采集的图像,在显示图像的过程中需要将原始数据的BayerRG8图像转化为cv::Mat类型,以便通过OpenCV显示。
class CSampleCaptureEventHandler :public ICaptureEventHandler
{
{
cv::Mat img(objImageDataPointer->GetHeight(),
objImageDataPointer->GetWidth(), CV_8UC3);
img.create(objImageDataPointer->GetHeight(),
objImageDataPointer->GetWidth(), CV_8UC3);
//假设原始数据是BayerRG8图像
void* pRGB24Buffer = objImageDataPointer->ConvertToRGB24(GX_BIT_0_7,GX_RAW2RGB_NEIGHBOUR, true);
memcpy(img.data, pRGB24Buffer, (objImageDataPointer->GetHeight()) * (objImageDataPointer->GetWidth()) * 3);
//显示图像
cv::imshow(“Imager1”, img);
cv::waitKey(1);
}
};
线阵相机初始化包括SDK初始化、采集设备设置、数据缓存申请及传输等流程。
IGXFactory::GetInstance().Init();//SDK初始化
m_pSampleCaptureEventHandle = new CSampleCaptureEventHandler();
//采集设备设置
m_AcqDevice = new SapAcqDevice(SapLocation(CStringA(“Linea_M4096-7um_1”), 0), NULL);
m_AcqDevice->SetConfigFile(“D:\Program Files (x86)\CamFiles\User\T_Linea_M4096-7um_Default_Default.ccf”);
//缓存申请
m_Buffers = new SapBufferWithTrash(MAX_BUFFER, m_AcqDevice);
//数据传输及回调函数
m_Xfer = new SapAcqDeviceToBuf(m_AcqDevice, m_Buffers, XferCallback, this);
m_Xfer->GetPair(0)->SetFramesPerCallback(m_nFramesPerCallback);
nFramesPerCallback = m_Xfer->GetPair(0)->GetFramesPerCallback();
开始采集时调用m_Xfer->Grab(),结束采集时调用m_Xfer->Freeze()。
2.2 基于MFC的OpenCV图像窗口显示程序设计
在基于MFC对话框的程序中将OpenCV的显示窗口附着在MFC的CPictureCtrl控件上,声明OpenCV窗口Imager1,根据CPictureCtrl控件大小调整OpenCV窗口Imager1的大小,并将其句柄附着在CPictureCtrl控件上。
cv::namedWindow(“Imager1”, cv::WINDOW_NORMAL);
CRect rect;
GetDlgItem(IDC_PIC)->GetWindowRect(rect);
cv::resizeWindow(“Imager1”, rect.Width(), rect.Height());
HWND hWnd = (HWND)cvGetWindowHandle(“Imager1”);
m_hOpenCVWnd = hWnd;
HWND hParent = ::GetParent(hWnd);
::SetParent(hWnd, GetDlgItem(IDC_PIC)->m_hWnd);
::ShowWindow(hParent, SW_HIDE)。
2.3 药粒计数处理程序设计
设计的药粒计数程序流程如图2所示,在图像预处理的基础上采用轮廓提取,根据轮廓面积进行筛选,滤除噪声干扰。判断其是否是“8”字型粘连[5-6],如果是则采用距离变换的方法进一步识别,若确认是“8”字型粘连则计数加1。在前后两帧图像中,处于图像边缘的药粒图像可能因显示不全而造成重复计数,利用线阵相机成像后相对位置不发生改变的特点,对横坐标相等且在前后两帧的上下边缘处,根据公式剔除。
图2 “8”字型粘连分割Fig.2 “8” type adhesive segmentation
图3 相邻两帧图像中药粒重复计数剔除Fig.3 Repeated counting of eliminated Chinese medicine granules in adjacent frames
图4 药粒计数处理程序流程Fig.4 Flow of drug counting processing program
其中,Cs1与Cs2表示区域S1和S2的圆度,Cs1+s2表示区域S1与S2拼接后形成的区域的圆度,xs1与xs2表示区域S1与S2的中心水平位置,T1、T2及T3为阈值。区域的圆度与中心可以通过边缘提取及外接矩形获得。
3 实验系统及运行结果
实物系统如图5所示,配置如表1所示。
表1 基于机器视觉的高速药粒分装装置实验设置Tab.1 Experimental setting of high speed drug dispensing device based on machine vision
图5 实验系统实物Fig.5 Experimental system object
系统界面及运行结果如图6所示,程序中设置了计数目标,模拟装瓶过程。图中红色矩形为识别出的“8”字型粘连,绿色与蓝色矩形为前后两帧重复计数剔除。
图6 基于机器视觉的高速在线药粒计数系统程序界面及计数结果Fig.6 Program interface and counting result of high speed on-line drug count system based on machine vision
从表2可以看出,系统计数精度达100%,可实现精准计数。
表2 计数实验结果Tab.2 Results of counting experiment
4 结论
为实现中药药粒的高速计数,结合Dalsa线阵相机SDK、Opencv 4.55及Visual Studio 2019,设计了基于机器视觉的高速在线药粒计数系统程序。从计数实验结果来看,此系统计数精度达100%,可满足药厂对药粒分装的精度要求,具有十分广阔的市场前景。