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

来源:互联网 发布:淘宝上的装修付款方式 编辑:程序博客网 时间:2024/05/29 05:12

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 vetorvoid 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 linevoid 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

0 0
原创粉丝点击