How to - Simplify this code? (heat map)

edited March 2018 in Arduino

So I have this code, it takes data from Arduino over serial and turns it into a heat map using a linear interpolation algorithm (not written by me). I'm no expert programmer, but would there be really any good way to simplify the algorithm or applycolor() it to make the heat map run faster? Right now it updates 1 time every 4 seconds or so, Arduino sends data 10 times a second (the thermal camera's maximum frequency)

import processing.serial.*;

Serial myPort;
String myString;

int j;
int m = 0;

int r = 8;  // number of rows in input array
int c = 8;  // number of columns in input array
int t = 200;  // parameter (array resize factor)
int rows = (r-1)*t;  // height of the heat map
int cols = (c-1)*t;  // width of the heat map

float[][] array = new float[r][c];  // input array
float[][] interp_array = new float[rows][cols]; // interpolated array
String[] list = new String[r*c];

void settings()
{
  size(cols, rows);
}

void setup()
{

  printArray(Serial.list());

  myPort = new Serial(this, Serial.list()[0], 9600);

  myPort.write(65);

  noStroke();
}

void draw()
{
  while (myPort.available() > 0 ) {

    //Expand array size to the number of bytes you expect
    byte[] inBuffer = new byte[1024];
    myPort.readBytesUntil('\n', inBuffer);

    if (inBuffer != null) {
      myString = new String(inBuffer);
      list = split(myString, ',');
      for (int i = 0; i < (list.length)/8; i++) {
        for (j = 0; j < (list.length)/8; j++) {
          array[j][i] = float(list[m]);
          m++;
        }
      }
      m = 0;
    }
  }
  bilinearInterpolation();  //these are IN the while loop
  applyColor();
}



void bilinearInterpolation() {  // Bi-linear Interpolation algorithm

  for (int i=0; i<r; i++) {
    for (int j=0; j<c; j++) {
      int x = j*t - 1;
      int y = i*t - 1;
      if (x<0)
        x=0;
      if (y<0)
        y=0;
      interp_array[y][x] = array[i][j];
    }
  }

  for (int y=0; y<rows; y++) {
    int dy1 = floor(y/(t*1.0));
    int dy2 = ceil(y/(t*1.0)); 
    int y1 = dy1*t - 1;
    int y2 = dy2*t - 1;
    if (y1<0)
      y1 = 0;
    if (y2<0)
      y2 = 0;
    for (int x=0; x<cols; x++) {
      int dx1 = floor(x/(t*1.0));
      int dx2 = ceil(x/(t*1.0));
      int x1 = dx1*t - 1;
      int x2 = dx2*t - 1;
      if (x1<0)
        x1 = 0;
      if (x2<0)
        x2 = 0;
      float q11 = array[dy1][dx1];
      float q12 = array[dy2][dx1];
      float q21 = array[dy1][dx2];
      float q22 = array[dy2][dx2];

      int count = 0;
      if (q11>0)
        count++;
      if (q12>0)
        count++;
      if (q21>0)
        count++;
      if (q22>0)
        count++;

      if (count>2) {
        if (!(y1==y2 && x1==x2)) {

          float t1 = (x-x1);
          float t2 = (x2-x);
          float t3 = (y-y1);
          float t4 = (y2-y);
          float t5 = (x2-x1);
          float t6 = (y2-y1);

          if (y1==y2) {
            interp_array[y][x] = q11*t2/t5 + q21*t1/t5;
          } else if (x1==x2) {
            interp_array[y][x] = q11*t4/t6 + q12*t3/t6;
          } else {
            float diff = t5*t6;
            interp_array[y][x] = (q11*t2*t4 + q21*t1*t4 + q12*t2*t3 + q22*t1*t3)/diff;
          }
        } else {
          interp_array[y][x] = q11;
        }
      } else {
        interp_array[y][x] = 0;
      }
    }
  }
}

void applyColor() {  // Generate the heat map 

  color c1 = color(0, 0, 255);  // Blue color
  color c2 = color(0, 255, 0);  // Green color
  color c3 = color(255, 0, 0);  // Red color
  color c4 = color(255, 255, 0);  // Yellow color

  for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
      float value = interp_array[i][j];
      color c;
      float fraction;

      if (value>=1 && value<2) {
        fraction = (value-1)/1.0;
        c = lerpColor(c1, c2, fraction);
      } else if (value>=2 && value<3) {
        fraction = (value-2)/1.0;
        c = lerpColor(c2, c3, fraction);
      } else if (value>=3 && value<5) {
        fraction = (value-3)/2.0;
        c = lerpColor(c3, c4, fraction);
      } else 
      c = c4;
      stroke(c);
      point(j, i);
    }
  }
}
Tagged:

Answers

  • Answer ✓

    First you have to work out which bit is taking all the time. It might not be where you think it is. You can do this crudely by adding println statements in draw just printing out a label and the current value of millis.

  • Can you explain lines 47 and 48?

    We don't have any data so it's hard for us to debug this.

  • This is why we don't post duplicates

  • edited March 2018

    I'm asking a different question so I didn't think this would be considered duplicated. But 47 and 48 is just reading the 64 values from the serial port and assigning it to its spot in the 8x8 array "array". The linear interpolation array (in the linear interpolation function) then takes these values, psuhes them through the linear interpolation function and spits back out an array of size (7 * t x 7 * t)

  • Hey, sorry for posting about the same code 3 times. I did some playing around and the real time taker is the applyColor() function. Because it applys color to 700x700 pixels (if variable t = 100). Is there any obvious way to shrink the "resolution" of the outputted screen but have it be the same size? Thanks!

  • edited March 2018

    Found out there is simply the scale(float); function.

    Added in scale(4.0) right before applyColor() is used in the draw() function. and multiplied cols and rows in the size() function by 4, too. This worked perfectly!

  • for (int i = 0; i < (list.length) / 8; i++) {
        for (j = 0; j < (list.length) / 8; j++) {
    

    My concern here is that normally for any kind of grid you'd use differing values in the middle clauses of the for statements. One would be the number of rows and one would be the number of columns, like you have elsewhere.

    But I don't know what list is so...

  • But the code over in the other thread doesn't have this in it, it uses r and c. So I'm wasting my time even thinking about it.

    And this is why we don't post duplicates.

  • edited March 2018

    Yeah. I get it. I had a different question to ask. Dont know why youre looking at the other thread to answer this thread. List[] is what the serial output is split into. Then in those lines of code you pasted I assign the value of list[m] to array[i][j]. array is 8x8 2d array, list (should) have length 64 so I assign the first 8 values to the first “row” of array and the second 8 values to the second “row” and so on.

Sign In or Register to comment.