processing_计算图像的梯度与切向,并用箭头和流线表示(附下载链接)

processing_计算图像的梯度与切向,并用箭头和流线表示

标签(空格分隔): java\processing


文档的下载页

1、彩色图像转灰色
将RGB三个色彩转变成一样的即可。

void bgrTogray(){
    for(int i=0;i<p1.width;i++){
        for(int j=0;j<p1.height;j++){
          int xy = i + p1.width * j;
          float r = red(p1.pixels[xy]);
          float g = green(p1.pixels[xy]);
          float b = blue(p1.pixels[xy]);
          int mix = int(r * 0.299f + g * 0.587f + b * 0.114f);
          if(mix>255)mix = 255;
          color c1 = color(mix,mix,mix);
          p1.pixels[xy] = c1;
        }
    }
}

效果:
image_1bfo1leb06ol17thkff1el0jdo9.png-1052.1kB
image_1bfo1lsrlnn8oin9bu1aphhecm.png-497.7kB

2、计算灰度图像的梯度场与切线场。
遍历整幅图像,用和上一行对应点的灰度值之查和右边点的灰度值之查的来代表该点的一个梯度向量(△x,△y),然后根据两直线垂直可以得到切线长的向量(-△y,△x)。
代码:

void calculateTangrads(){
  for(int i=0;i<grads.size();i++){
   ArrayList a = (ArrayList)grads.get(i);
   float temc = (float)a.get(0);
   float temp2 = (float)a.get(1);
   ArrayList b = new ArrayList();
   b.add(-temp2);
   b.add(temc);
   tangrads.add(b);
  }
}

void calculateGrads(){
  for(int i=0;i<c.height;i++){
     if(i == c.height - 1){    // copy 
      for(int k = 0;k<c.width;k++){
          grads.add(grads.get( (i-1)*c.width + k ));
      }
      break;
    }
    for(int j=0;j<c.width;j++){
       int xy = j + c.width * i;
       int x1y = j + 1 +c.width * i;
       int xy1 = j + c.width * (i + 1);
       if( j == c.width - 1){    //copy the last list
         grads.add(grads.get(grads.size()-1));
         continue;
       }
       ArrayList a = new ArrayList();
       float g_x = red(c.pixels[x1y]) - red(c.pixels[xy]);
       float g_y = red(c.pixels[xy1]) - red(c.pixels[xy]);
       a.add(g_x);a.add(g_y);
       grads.add(a);
    }
  }
  value++;
}

3、用箭头表示梯度场和切线场
直线好画,知道点及其对应向量,可以画出一段从该点出发的向量。关键是如何画箭头。这里我的想法是通过求出三个点,然后根据三个点画一个三角形代表箭头。
那么三个点如何选取呢?第一个点是向量的末端点,第二、第三个点是在垂直于向量的直线上找到的关于向量对称的两个点。
image_1bfo3aoho6lfur51altb9811h99.png-147.5kB
代码:

//draw arrow of a vetor
void drawTriangle(float x1,float y1,float x2,float y2){
  float detx = x2 - x1;float dety = y2 - y1;
  float x3,y3;  //  one point on the line x1/y1 x2/y2
  float length = sqrt(detx*detx + dety*dety);
  float interval_distance = length/10.0f;    //  distance
  x3 = x2 - interval_distance * (detx / length);
  y3 = y2 - interval_distance * (dety / length);
  float cx,cy,p2x,p2y;
  cx = x3 - interval_distance * (-dety / length);
  cy = y3 - interval_distance * ( detx / length);
  p2x = x3 + interval_distance * (-dety / length);
  p2y = y3 + interval_distance * ( detx / length);
  triangle(x2, y2, cx, cy, p2x, p2y);
}

效果:
image_1bfo3dp1g1gt21hg92gu1gr0dg8m.png-664.6kB
image_1bfo41r8817t9apg1mkc10jm1la129.png-29.3kB
image_1bfo3k4lvl5a1t2kkegiko1cui1g.png-200.7kB

4、用流线表示切线场
流线主要运用切向量场,随机选定图片上一个点,画出它的切向量,再取切向量末端点的切向量,继续画下去,直到画出图像或者切向量为零向量或者达到一定的步数。
代码:

void seed(){
  for(int i=0;i<num_max;i++){
    ArrayList pos = new ArrayList();
    float randomx = random(0,c.width-1);
    float randomy = random(0,c.height-1);
    pos = (ArrayList)(tangrads.get(((int)randomx + (int)randomy * c.width)));
    drawStreamLine(pos,randomx,randomy);
  }
}
//draw  stream line
void drawStreamLine(ArrayList seed,float x,float y){
  ArrayList oldpos = new ArrayList();
  ArrayList pos = new ArrayList();
  oldpos.add(x);oldpos.add(y);
  pos.add(x);pos.add(y);

  int maxstep = 1000;
  float step = 0.1f;
  stroke(255,0,0);
   noFill();
      beginShape();
      int n = 0;
      while(n<= maxstep)
      {
        vertex((float)pos.get(0), (float)pos.get(1));
        if((float)seed.get(0) == 0.0f &&(float)seed.get(1) == 0.0f)  break;
        ArrayList newpos = new ArrayList();
        float newx = (float)oldpos.get(0) + (float)seed.get(0) * step;
        float newy = (float)oldpos.get(1) + (float)seed.get(1) * step;
        if(newx<0||newx>c.width-1||newy<0||newy>c.height-1)  break;
        seed = (ArrayList)tangrads.get(((int)newx + c.width * (int)newy));
        newpos.add(newx);newpos.add(newy);
        pos = newpos;
        oldpos = pos;
        n++;
      }
      endShape();
}

效果:
GIF.gif-3563.6kB

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值