processing视觉抓取
博客专区 > YANG_G 的博客 > 博客详情
processing视觉抓取
YANG_G 发表于4个月前
processing视觉抓取
  • 发表于 4个月前
  • 阅读 23
  • 收藏 1
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

接之前的scara机械臂,我用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);
}

 

共有 人打赏支持
粉丝 2
博文 4
码字总数 10801
×
YANG_G
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: