Skip to content

銅卷位置檢測及尺寸測量

專案簡介

專案背景

利用雲臺感測器拍攝影像,對需要進行包裝入箱的銅箔卷,檢測其在鐵托盤上的前後左右及高度位置,為機械臂的抓取提供引導,同時讀取產品上的二維碼資訊以匹配裝銅箔的木箱規格; 其次檢測木箱規格以及在小車上的左右位置,以核對木箱規格,同時為機械臂抓取銅箔入箱提供位置引導資訊。

本地圖片

相機選型

SICK雲臺線掃

檢測要求

X向精度 ≤ 0.025mm
Y向精度 ≤ 0.03mm
測量週期 ≤ 2s

解決方案

Vision-Studio軟體針對3D點雲進行處理,首先通過Blob工具進行銅卷定位,輸出銅卷的位置等資訊,再通過圓柱工具擬合出圓柱,從而進行體積的計算 。

設計思路

本地圖片

執行效果展示

  • 工程結果展示:

    本地圖片

  • HMI結果展示:

    本地圖片

專案流程

一、初始化

  1. 選擇Lua脚本语言工具,全域性變數初始化,建立待接收資料的csv檔案。
  • 拼接表頭字串,儲存初始化csv檔案

經驗

.. 用於string型別字串拼接

part1 = "Hello, "
part2 = "world!"
result = part1 .. part2
print(result) # 輸出: Hello, world!

,作為分隔符,分割每個資料項

lua
--初始化全局变量
SetIntVariable('CurrentTime',0)


write = ''

--对文件进行判断,如果当前文件不存在,则生成文件
if FileExists("./H.csv") == false then  
    write = write .. 'Time,'  
    for i = 1,15,1 do     
        write = write .. 'h' .. i .. ","
    end
    write = write .. '\n'
    --"\n"表示换行
end
-- 每行第一列写入当前时间
write = write .. os.date("%Y_%m_%d %H:%M;%S") .. ","  
-- 将刚才的内容写入csv文件中
WriteToFile("./H.csv",write)     
  
--生成用于拼接的字符串 
write = ''
if FileExists("./Position.csv") == false then  
    write = write .. 'Time,'  
    for i = 1,15,1 do     
        write = write .. 'x' .. i .. ","
        write = write .. 'y' .. i .. ","
        write = write .. 'z' .. i .. ","
        write = write .. ','
    end
    write = write .. '\n'
end
-- 每行第一列写入当前时间
write = write .. os.date("%Y_%m_%d %H:%M;%S") .. ","    
-- 将刚才的内容写入csv文件中
WriteToFile("./Position.csv",write)
  1. 選擇加载点云工具,獲取點雲。

二、預處理

本地圖片

  1. 選擇3D变换工具,將影像繞x軸反方向旋轉90度。

  2. 選擇3D裁切工具,將圓柱切割開並輸出到IM1中。

本地圖片

  1. 選擇3D下采样工具,減少點雲中點的個數,方便後續操作。

  2. 選擇3D离群点滤波工具,過濾掉雜點。

本地圖片

三、圓柱高度與位置測量

本地圖片

  1. 選擇3D斑点工具,分割出15個圓柱。

本地圖片

  1. 選擇lua语言脚本,繫結上一步運算元變數中bolb位置變數,編寫lua指令碼儲存儲存圓柱位置至檔案中。

  2. 選擇3D圆柱工具,將銅卷擬合成圓柱

本地圖片

四、資料儲存

選擇lua语言脚本,繫結上一步輸出的運算元變數(圓柱的兩頂點座標),計算得到尺寸資訊並儲存至檔案中。

  • 拼接擬合的圓柱尺寸資訊到字串並將字串儲存到全域性變數

  • 儲存單個圓柱尺寸資訊到全域性變數

經驗

string.format 用於格式化字串 %.nf表示將浮點數格式化為保留 n 位小數。

pi = 3.14159 str = string.format("Pi is approximately %.3f", pi) print(str) -- 輸出: Pi is approximately 3.141

lua
write = ""

write = write .. string.format("%.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f,"
    ,math.abs(Circle1.Bottom.X - Circle1.Top.X),math.abs(Circle2.Bottom.X - Circle2.Top.X),
    math.abs(Circle3.Bottom.X - Circle3.Top.X),math.abs(Circle4.Bottom.X - Circle3.Top.X),
    math.abs(Circle3.Bottom.X - Circle5.Top.X),math.abs(Circle6.Bottom.X - Circle3.Top.X),
    math.abs(Circle3.Bottom.X - Circle7.Top.X),math.abs(Circle8.Bottom.X - Circle3.Top.X),
    math.abs(Circle3.Bottom.X - Circle9.Top.X),math.abs(Circle10.Bottom.X - Circle3.Top.X),
    math.abs(Circle3.Bottom.X - Circle11.Top.X),math.abs(Circle12.Bottom.X - Circle3.Top.X),
    math.abs(Circle3.Bottom.X - Circle13.Top.X),math.abs(Circle14.Bottom.X - Circle3.Top.X),
    math.abs(Circle3.Bottom.X - Circle15.Top.X))


SetFloatVariable("h" .. "1" ,math.floor(1000*math.abs(Circle1.Bottom.X - Circle1.Top.X))/1000)
SetFloatVariable("h" .. "2" ,math.floor(1000*math.abs(Circle2.Bottom.X - Circle2.Top.X))/1000)
SetFloatVariable("h" .. "3" ,math.floor(1000*math.abs(Circle3.Bottom.X - Circle3.Top.X))/1000)
SetFloatVariable("h" .. "4" ,math.floor(1000*math.abs(Circle4.Bottom.X - Circle4.Top.X))/1000)
SetFloatVariable("h" .. "5" ,math.floor(1000*math.abs(Circle5.Bottom.X - Circle5.Top.X))/1000)
SetFloatVariable("h" .. "6" ,math.floor(1000*math.abs(Circle6.Bottom.X - Circle6.Top.X))/1000)
SetFloatVariable("h" .. "7" ,math.floor(1000*math.abs(Circle7.Bottom.X - Circle7.Top.X))/1000)
SetFloatVariable("h" .. "8" ,math.floor(1000*math.abs(Circle8.Bottom.X - Circle8.Top.X))/1000)
SetFloatVariable("h" .. "9" ,math.floor(1000*math.abs(Circle9.Bottom.X - Circle9.Top.X))/1000)
SetFloatVariable("h" .. "10" ,math.floor(1000*math.abs(Circle10.Bottom.X - Circle10.Top.X))/1000)
SetFloatVariable("h" .. "11" ,math.floor(1000*math.abs(Circle11.Bottom.X - Circle11.Top.X))/1000)
SetFloatVariable("h" .. "12" ,math.floor(1000*math.abs(Circle12.Bottom.X - Circle12.Top.X))/1000)
SetFloatVariable("h" .. "13" ,math.floor(1000*math.abs(Circle13.Bottom.X - Circle13.Top.X))/1000)
SetFloatVariable("h" .. "14" ,math.floor(1000*math.abs(Circle14.Bottom.X - Circle14.Top.X))/1000)
SetFloatVariable("h" .. "15" ,math.floor(1000*math.abs(Circle15.Bottom.X - Circle15.Top.X))/1000)

write = write .. "\n"
-- 将数据写入表中
WriteToFile("./H.csv",write)

Vision Studio