今天公司组织发福利,端午的福利,粽子、、、 也不是直接的发粽子。而是给你礼品卷,自己选择相应的礼品进行兑换。
就是这么个东西,由于我们公司一直致力于做工业智能化,我就查了一下粽子的生产流程:
我的个乖乖,从来没有关注过粽子的生产,今天以卡,基本上属于人工生产的方式,这怎么能忍。一个做智能制造的,怎么能忍受人工生产呢。所以,我就农了这篇文章,表达一下我的看法,当然了,实现全自动的可能性应该没有,应为预算太高,粽子一年就买几天,回本太慢了。
基本上都属于人工,那么我们就来对粽子生产的的某些功能进行升级吧!
粽子的分类以及抓取放到包装盒
由于我这里没有粽子的产线,智能放一个大体上相同的
我们通过前端的视觉拍照,得到粽子的大小以及在传送带上的位置,把他发送给机器人,机器人根据得到的数据在后方将粽子抓取到相应的包装盒。
前期标定
我们通过手眼标定的方式将机器人和相机标定到同一个坐标系下面,具体操作不走如下:
1.我们首先在视觉相机下方找到九个点,平且求出9个点在相机坐标下的像素坐标值P(i);
2.传送带万千移动,我们记录一下传送带往前走了的编码的脉冲量M;
3.将九个点的位置以机器人为坐标,记录下9个点的机器人坐标数据q(i);
我们通过机器人端的开发包建立随动坐标,将我们的数据传入到随动坐标中;
视觉这块,我们将的到的机械的坐标和视觉的坐标合二为一,通过halcon9点标定的方式来进行一个标定;
*图像坐标
area_center(SortedRegions,Area,Row,Column) %
Column_robot := [275,225,170,280,230,180,295,240,190]
*机器人9点的列坐标
Row_robot := [55,50,45,5,0,-5,-50,-50,-50]
*机器人9点的行坐标
vector_to_hom_mat2d(Row,Column,Row_robot,Column_robot,HomMat2D)
*求解变换矩阵,HomMat2D是图像坐标和机械手坐标之间的关系
`affine_trans_point_2d(HomMat2D,Row2,Column2,Qx,Qy)’
'*由像素坐标和标定方式求出机器人基础坐标系中的坐标 `
视觉程序
我们首先以粽子的原图作为模型,通过模型识别定位
示例如下:
* ------------------------------------------------------------------------------------------------
* This example program uses shape-based matching to align ROIs for the measure
* tool, which then inspects individual razor blades.
* The program can be run in two modes: (1) with the full affine transformation
* (2) using translate_measure
* Modify the next line to switch between the modes.
USING_TRANSLATE_MEASURE := 0
* ------------------------------------------------------------------------------------------------
* general configuration of HDevelop
dev_update_window ('off')
* image acquisition and window size
read_image (ModelImage, 'razors1')
get_image_pointer1 (ModelImage, Pointer, Type, Width, Height)
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'white', WindowHandle)
dev_set_part (0, 0, Height - 1, Width - 1)
dev_display (ModelImage)
* colors and other settings for the visualization
dev_set_color ('cyan')
dev_set_draw ('margin')
dev_set_line_width (2)
stop ()
* ------------------- start of the application ----------------
* -> select the model object
Row1 := 46
Column1 := 57
Row2 := 79
Column2 := 94
gen_rectangle1 (ROIPart1, Row1, Column1, Row2, Column2)
gen_rectangle1 (ROIPart2, Row1 + 364, Column1 + 13, Row2 + 364, Column2 + 13)
union2 (ROIPart1, ROIPart2, ModelROI)
area_center (ModelROI, Area, CenterROIRow, CenterROIColumn)
dev_display (ModelImage)
dev_display (ModelROI)
stop ()
* -> create the model
reduce_domain (ModelImage, ModelROI, ImageROI)
create_shape_model (ImageROI, 4, 0, 0, 'auto', 'none', 'use_polarity', 30, 10, ModelID)
inspect_shape_model (ImageROI, ShapeModelImage, ShapeModelRegion, 1, 30)
get_shape_model_contours (ShapeModel, ModelID, 1)
dev_clear_window ()
dev_set_color ('blue')
dev_display (ShapeModelRegion)
stop ()
* step 1: create variables describing the measurement ROIs and display them
Rect1Row := 244
Rect1Col := 73
DistColRect1Rect2 := 17
Rect2Row := Rect1Row
Rect2Col := Rect1Col + DistColRect1Rect2
RectPhi := rad(90)
RectLength1 := 122
RectLength2 := 2
gen_rectangle2 (MeasureROI1, Rect1Row, Rect1Col, RectPhi, RectLength1, RectLength2)
gen_rectangle2 (MeasureROI2, Rect2Row, Rect2Col, RectPhi, RectLength1, RectLength2)
dev_display (ModelImage)
dev_set_color ('yellow')
dev_display (MeasureROI1)
dev_display (MeasureROI2)
* translate measurement ROIs to lie on XLD model (without clipping!)
get_system ('clip_region', OriginalClipRegion)
set_system ('clip_region', 'false')
move_region (MeasureROI1, MeasureROI1Ref, -CenterROIRow, -CenterROIColumn)
move_region (MeasureROI2, MeasureROI2Ref, -CenterROIRow, -CenterROIColumn)
set_system ('clip_region', OriginalClipRegion)
DistRect1CenterRow := Rect1Row - CenterROIRow
DistRect1CenterCol := Rect1Col - CenterROIColumn
DistRect2CenterRow := Rect2Row - CenterROIRow
DistRect2CenterCol := Rect2Col - CenterROIColumn
if (USING_TRANSLATE_MEASURE != 0)
* -> measure objects are created only once in advance and then translated later
gen_measure_rectangle2 (Rect1Row, Rect1Col, RectPhi, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle1)
gen_measure_rectangle2 (Rect2Row, Rect2Col, RectPhi, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle2)
endif
stop ()
* step 2: find the objects in another image
read_image (SearchImage, 'razors2')
dev_display (SearchImage)
find_shape_model (SearchImage, ModelID, 0, 0, 0.8, 0, 0.5, 'least_squares', 0, 0.7, RowCheck, ColumnCheck, AngleCheck, Score)
if (|Score| > 0)
for i := 0 to |Score| - 1 by 1
* step 3: determine the affine transformation
vector_angle_to_rigid (0, 0, 0, RowCheck[i], ColumnCheck[i], AngleCheck[i], MovementOfObject)
affine_trans_contour_xld (ShapeModel, ModelAtNewPosition, MovementOfObject)
dev_display (ModelAtNewPosition)
* step 4: measure width and distance of the teeth
* -> display the moved ROIs
affine_trans_region (MeasureROI1Ref, MeasureROI1AtNewPosition, MovementOfObject, 'constant')
affine_trans_region (MeasureROI2Ref, MeasureROI2AtNewPosition, MovementOfObject, 'constant')
dev_display (MeasureROI1AtNewPosition)
dev_display (MeasureROI2AtNewPosition)
affine_trans_pixel (MovementOfObject, DistRect1CenterRow, DistRect1CenterCol, Rect1RowCheck, Rect1ColCheck)
affine_trans_pixel (MovementOfObject, DistRect2CenterRow, DistRect2CenterCol, Rect2RowCheck, Rect2ColCheck)
if (USING_TRANSLATE_MEASURE != 0)
* -> translate the already created measure objects
translate_measure (MeasureHandle1, Rect1RowCheck, Rect1ColCheck)
translate_measure (MeasureHandle2, Rect2RowCheck, Rect2ColCheck)
measure_pairs (SearchImage, MeasureHandle1, 2, 25, 'negative', 'all', RowEdge11, ColEdge11, Amp11, RowEdge21, ColEdge21, Amp21, Width1, Distance1)
measure_pairs (SearchImage, MeasureHandle2, 2, 25, 'negative', 'all', RowEdge12, ColEdge12, Amp12, RowEdge22, ColEdge22, Amp22, Width2, Distance2)
else
* -> create new measure objects and destroy them after the measurement
RectPhiCheck := RectPhi + AngleCheck[i]
gen_measure_rectangle2 (Rect1RowCheck, Rect1ColCheck, RectPhiCheck, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle1)
gen_measure_rectangle2 (Rect2RowCheck, Rect2ColCheck, RectPhiCheck, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle2)
* step 5: perform the measurement
measure_pairs (SearchImage, MeasureHandle1, 2, 25, 'negative', 'all', RowEdge11, ColEdge11, Amp11, RowEdge21, ColEdge21, Amp21, Width1, Distance1)
measure_pairs (SearchImage, MeasureHandle2, 2, 25, 'negative', 'all', RowEdge12, ColEdge12, Amp12, RowEdge22, ColEdge22, Amp22, Width2, Distance2)
close_measure (MeasureHandle1)
close_measure (MeasureHandle2)
endif
* step 6: check for too short or missing teeth
NumberTeeth1 := |Width1|
NumberTeeth2 := |Width2|
dev_set_color ('red')
if (NumberTeeth1 < 37)
for j := 0 to NumberTeeth1 - 2 by 1
if (Distance1[j] > 4.0)
RowFault := round(0.5 * (RowEdge11[j + 1] + RowEdge21[j]))
ColFault := round(0.5 * (ColEdge11[j + 1] + ColEdge21[j]))
disp_rectangle2 (WindowHandle, RowFault, ColFault, 0, 4, 4)
dev_open_window (0, Width + 20, 80, 80, 'black', WindowHandleZoom)
dev_set_part (RowFault - 10, ColFault - 10, RowFault + 10, ColFault + 10)
dev_display (SearchImage)
disp_rectangle2 (WindowHandleZoom, RowFault, ColFault, 0, 4, 4)
stop ()
dev_close_window ()
dev_set_part (0, 0, Height - 1, Width - 1)
endif
endfor
endif
if (NumberTeeth2 < 37)
for j := 0 to NumberTeeth2 - 2 by 1
if (Distance2[j] > 4.0)
RowFault := round(0.5 * (RowEdge12[j + 1] + RowEdge22[j]))
ColFault := round(0.5 * (ColEdge12[j + 1] + ColEdge22[j]))
disp_rectangle2 (WindowHandle, RowFault, ColFault, 0, 4, 4)
dev_open_window (0, Width + 20, 80, 80, 'black', WindowHandleZoom)
dev_set_part (RowFault - 10, ColFault - 10, RowFault + 10, ColFault + 10)
dev_display (SearchImage)
disp_rectangle2 (WindowHandleZoom, RowFault, ColFault, 0, 4, 4)
stop ()
dev_close_window ()
dev_set_part (0, 0, Height - 1, Width - 1)
endif
endfor
endif
dev_set_color ('yellow')
stop ()
endfor
endif
* ------------------- end of the application -----------------
* clean up
if (USING_TRANSLATE_MEASURE != 0)
close_measure (MeasureHandle1)
close_measure (MeasureHandle2)
endif
dev_update_window ('on')
clear_shape_model (ModelID)
机器人配合
在我们做完酒店标定以后,机器人只需要将视觉传过来的坐标带入到随动坐标系中,这样就能够得到准确的随动坐标。
结束语
本次我们提升了包装的速率,后续我们将对整个产线都实行自动化的功能升级;