saveFrame cuts off top and left side of frame

Hey yall, I am using an interpolation algorithm to smooth an image of a heatmap im making from an 8x8 array of thermisistors. It displays an 8x8 picture of circles, but the top row and left column are cut in half for some reason, how do I fix this? I can post code if the solution isnt some simple command

Can you please post a MCVE? Note that this should not be your full program, but should be just enough code to reproduce the problem. Does this happen if you just draw a single hard-coded circle?

I’m very new to this language. I managed to figure out what is exactly needed to do this project. I’m not sure how to hard code a circle but here’s my code (not posting the method bilinearinterpolation because it’s very long and doesn’t effect anything except the size of an array

Can you please post your code as text? We can’t copy or paste text that’s in an image. Also please try to narrow the problem down. Right now your code has a lot of logic that will make this harder to debug.

And by hard-coding an image, I just meant a program like this:

ellipse(width/2, height/2, width, height);
saveFrame();

If you run a simple program like this, do you see the problem?

I do not see a problem, just a circle in the upper left with nothing cut off.

Code:

import processing.serial.*;

Serial myPort;
String myString;

int j;
int m = 0;

float n = 200;  //screen scaling factor

int r = 8;  // number of rows in input array
int c = 8;  // number of columns in input array
int t = 1;  // 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*int(n), rows*int(n));
}

void setup()
{
  myPort = new Serial(this, "COM3", 115200);
  noStroke();
}

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

    //Expand array size to the number of bytes you expect
    byte[] inBuffer = new byte[2048];
    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 OUT the while loop
  scale(n);
  applyColor();
  saveFrame("randomTest/screen-#####.png");
  println(frameRate);
}



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);
    }
  }
}

It’s actually simple. You just need to put ellipseMode(CORNER) in your setup and it should work.

That didn’t do anything because im not using ellipses, im using points.

I think it is just because of the way your points are drawn.

It looks like the coordinates you give are the center of the points so if you don’t want them to be cut off, you need to translate your coordinates by the radius of your points to the left and to the bottom.

Why don’t you use ellipse() instead of point(), I think you would have more controls?

2 Likes

Okay that sounds reasonable, within the point(i, j) function do I just make it point(i - radius, j - radius)?

Mitchell Ruffing

i + radius and j + radius but yes that’s the idea.

Hi Aigos,
I tried using your code above with my AGM8833 Thermal Camera but it doesn’t seem to do more than display a constant color. Can you help?
Joe

Well I have my amg8833 hooked up to an esp 32 feather microcontroller. I’m sure you have a similar setup. The amg8833 comes with ARDUINO IDE code that reads and prints the temperatures to the serial monitor. I edited it to print it with a comma inbetween them (which then processing reads from the serial monitor and splits it up based on where the commas are). The processing algorithm expects a value between 1-5, so I have the arduino code edit each value to be between 1-5 instead of 0-80. Don’t have my laptop with the code now so this is the best I can explain it. Let me know if you need anything else clarified

Thank you. I think I understand. I will look at editing the serial print to include commas and divide temp print by 16 if I understand you correctly. I’m very new at this but excited to be learning so much.

Aigo,

Fixed your above problem like this:

point(j+.5, i+.5)

Okay, I’ve done some tweaking but only the first DOT in my heat map is responding to temperature change.
Pixels

Please provide your latest code. No screenshots. Copy and paste, select code and hit the </> button before publishing your post so to format your code.

Kf

import processing.serial.*;

Serial myPort;
String myString;

int j;
int m = 0;

float n = 200;  //screen scaling factor

int r = 8;  // number of rows in input array
int c = 8;  // number of columns in input array
int t = 1;  // 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*int(n), rows*int(n));
}

void setup()
{
  myPort = new Serial(this, "COM3", 115200);
  noStroke();
}

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

    //Expand array size to the number of bytes you expect
    byte[] inBuffer = new byte[2048];
    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 OUT the while loop
  scale(n);
  applyColor();
  saveFrame("randomTest/screen-#####.png");
  println(frameRate);
}



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+.5, i+.5);
    }
  }
}`Preformatted text``Preformatted text

`