这篇文章主要介绍“processing怎么实现视觉抓取小程序”,在日常操作中,相信很多人在processing怎么实现视觉抓取小程序问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”processing怎么实现视觉抓取小程序”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
用processing写一个简单的视觉抓取小程序:识别红蓝绿色块并顺序抓放。
import processing.serial.*;
import processing.video.*;
Serial Port;
Capture cam;
float[][] kernel ={{0.111,0.111,0.111},
{0.111,0.111,0.111},
{0.111,0.111,0.111}
};//卷积核
//中间像素的灰度值等于周围像素的红色分量减去蓝绿色分量的平均值
//从而使没有红色特征的像素灰度值变为零
//相当于滤镜的效果,修改卷积核的参数,可以达到不一样的效果
int sub_x=0,sub_y=0;//物体中心的像素坐标
float pre_x=0,pre_y=0;//前一帧物体中心的像素坐标
float tar_x=80,tar_y=80;//目标坐标,机械手的坐标
boolean event=false;//坐标计算事件
int c=0;
void setup()//初始化
{
String portName = Serial.list()[0];
Port = new Serial(this, portName, 115200);//连接串口
size(640,480);//屏幕大小
String[] cameras = Capture.list();
printArray(cameras);//打印可使用的相机
cam = new Capture(this, cameras[0]);
cam.start();//启动相机
frameRate(30);//帧率
Port.write("G5 B90\r\n");
Port.write("G28\r\n");
Port.write("G1 X80 Y80 Z40\r\n");
Port.write("G5 B50\r\n");//移动到初始位置
delay(6000);//延迟,避免摄像头刚打开时的波动
}
void draw()//循环
{
if (cam.available() == true)
{
cam.read();
image(cam, 0, 0, width, height);
cam.loadPixels();
int sum_x=0,sum_y=0;//所有红色像素坐标的和
int m=1;//红色像素的个数
for(int y=1;y<cam.height-1;y++)//排除第一行、最后一行、第一列、最后一列像素(这几个地方周围的像素不完整)
{
for(int x=1;x<cam.width-1;x++)//经过所有像素
{
float sum=0;//最终的灰度值
for(int ky =-1;ky<=1;ky++)
{
for(int kx=-1;kx<=1;kx++)//周围9个像素(包括自身)
{
int pos =(y+ky)*cam.width+(x+kx);//将xy坐标换算成pixels[]数组中的位置,pixels[]数组是可以直接调用的储存像素的一维数组(从左到右从上到下)
int R = (cam.pixels[pos]>> 16) & 0xFF; //取颜色分量,与red()功能相似
int G = (cam.pixels[pos] >> 8) & 0xFF;
int B = cam.pixels[pos] & 0xFF;
float val=0;
switch(c)//顺序抓取红蓝绿色块
{
case 0:
val =R-1.5*B-1.5*G;
break;
case 1:
val =B-1.5*R-1.5*G;
break;
case 2:
val =G-0.5*B-1*R;
break;
}
//1.5为比例系数,改大可以让红色更突出
sum +=kernel[ky+1][kx+1]*val;//计算灰度值
}
}
if(sum>0)//新的灰度值非零
{
sum_x=sum_x+x;
sum_y=sum_y+y;//累加坐标
m=m+1;//计数
}
}
}
pre_x=sub_x;
pre_y=sub_y;//前一帧的物体中心
sub_x=sum_x/m;
sub_y=sum_y/m;//取平均,计算出物体中心像素坐标
cam.updatePixels();
fill(#FF0000);
}
line(sub_x,0,sub_x,480);
line(0,sub_y,640,sub_y);//作物体中心的两条交叉线
if(abs(sub_x-pre_x)<5&&abs(sub_y-pre_y)<5&&sub_x>5&&sub_y>5)//判断是否在移动(波动小于5个像素即为静止),是否存在物体(没有物体时默认为0,为避免波动,这里设置成5)
{
if(event==true)//如果物体存在,机械手静止,且事件被触发,则进行计算
{
tar_x=tar_x-(0.0625*sub_x-20);
tar_y=tar_y-(15-0.0625*sub_y);//把像素坐标转化成绝对坐标,根据实际比例
event=false;//关闭计算事件,即只执行一次计算
Port.write("G1 X"+tar_x+" Y"+tar_y+"\r\n");//移动到目标位置
delay(100);//延迟,减小波动
}
}
else //如果机械手在移动,触发计算事件,但不执行计算,为机械手静止时计算做准备
event=true;
/*由于机械手的通讯以及动作上有延迟,速度远赶不上摄像头对图像识别的速度,
所以仅让机械臂在静止时进行一次计算*/
if(sub_x<5&&sub_y<5)
{
if(c<3)
c=c+1;
else
c=0;
}
float mx=tar_x;
float my=tar_y+32;//手抓中心对的坐标,摄像头和手抓有32的y偏移量
if(sub_x>315&&sub_x<325&&sub_y>235&&sub_y<245)//当物体在画面中心时(+-5个像素)
{
//执行以下动作
Port.write("G1 X"+mx+'Y'+my+"Z12 F1200\r\n");
delay(1500);//充分延时
for(int i=50;i<=150;i+=5)
{
Port.write("G5 B"+i+"\r\n");
delay(50);
}
delay(500);
Port.write("G1 Z30\r\n");
delay(1000);
switch(c)//顺序摆放红蓝绿色块
{
case 0:
Port.write("G1 X150 Y120\r\n");break;
case 1:
Port.write("G1 X150 Y100\r\n");break;
case 2:
Port.write("G1 X150 Y80\r\n");break;
}
delay(1500);
Port.write("G1 Z10\r\n");
delay(500);
for(int j=150;j>=50;j-=5)
{
Port.write("G5 B"+j+"\r\n");
delay(50);
}
delay(500);
Port.write("G1 X80 Y80 Z40\r\n");
delay(1500);
if(c<3)
c=c+1;
else
c=0;
}
println(tar_x);
println(tar_y);
}
到此,关于“processing怎么实现视觉抓取小程序”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/u/3503462/blog/1524828