How to get polar coordinates of pixels in an image?

Hi all,

I am trying to print the polar coordinates of black pixels in an .jpg image using processing.
What is a way or formula to do this?

Your problem breaks down into the following steps:

  • Having a basic, empty sketch.
  • Loading an image.
  • Displaying an image (maybe).
  • Looping over all the pixels in an image.
  • Determining if a pixel is a black pixel.
  • Defining an origin and coordinate system that is the basis for you polar coordinate system.
  • Converting a (x,y) position into a (a, r) polar position.
  • Recording the (a, r) positions, possibly in some sort of data structure(?).
  • Maybe saving those positions to a file.

The converting of positions itself entail finding the distance between the origin and the (x,y) point (which means a call to dist()), and an angle between two points (which means a call to atan2(), I think).

It’s impossible to help you more without doing the whole thing for you, because we have no idea which sub-problem you are stuck on. Attempt to write some code and post your attempt for more help.

2 Likes

I simply need a formula (in code form) to convert 2d or 1d pixel indices to linear coordinates along a archimedean spiral. Imagine that the spiral is overlaying the image. I need to know what the pixel indices are under points along the spiral.

Here is what I have so far but it doesn’t do spiral/polar yet:

PImage input;// The selected image
String[] output;// The output file

void setup(){
  size(300, 300);
  output = new String[1];
  output[0] = "";// Avoid "null" at beginning
  selectInput("Select an image to process", "select");
}

void select(File selection){
  if(selection == null){
    exit();// exit if the input is null
  }else{
    input = loadImage(selection.getAbsolutePath());// load selected image
    input.resize(width, height);// reszie
    input.filter(THRESHOLD, 0.5);// make everything black and white
    
    input.loadPixels();
    for(int i = 0; i < input.pixels.length; i ++){// loop through all pixels
      if(input.pixels[i] == color(0)){
        output[0] += i + "\n";// if the pixel is black, write the position to the file
      }
    }
    saveStrings("cmds.txt", output);// save everything
    println("done");
  }
}

int x,y,dx,dy,steps;
float theta;

void setup(){
size(500,500);
x=250;y=250;
steps=1;
stroke(255);
background(0);
}

void draw(){
dx=int(cos(theta));
dy=int(sin(theta));
for(int i=0;i<steps;i++){
x+=dx;y+=dy;
point(x,y);
}
steps++;
steps++;
theta+=PI/2;
if(theta>6.28){theta=0;}

}

Maybe you simply need a formula but there is no magical one. @TfGuy44 is right, there are some steps that you need to go through that we can’t do for you.

The most important one is this one

Draw on a piece of papers the coordinate system of your image. Then decide the origin of you new system (the polar one), define your 0 degree angle and from there we can help you with the formula.

The equivalent statement to get(x, y) using pixels[] is pixels[y*width+x].

This is what I have now. But it generates a blank black pixel coordinates file which is incorrect.

// A Polar coordinate, radius now starts at 0 to spiral outwards
//float r = 0;
int z = 1;
float r = 0;
float theta = 0;
//float theta = 0;
PImage input;
String[] output;

void setup() {
  size(300, 300);
  output = new String[1];
  output[0] = "";
  selectInput("select an image to process", "select");
}
void select(File selection){
  if (selection == null){
    exit();
  }
  else {
    input = loadImage(selection.getAbsolutePath());
    input.resize(width, height);
    input.filter(THRESHOLD, 0.5);
    input.loadPixels();

//void draw() {
  while (z < 90000) {
  // Polar to Cartesian conversion
  float x = r * cos(theta);
  float y = r * sin(theta);

  
  int xx = int((x+width/2));
  int yy = int((y+height/2));
  int pixelz = get(xx,yy);
  if (pixelz == color(0)) {
    output[0] += z + "\n";
  //point(xx, yy);
  }

  // Increment the angle
  theta += 0.01;
  // Increment the radius
  r += 0.003; //0.001 covers all pixels
  z += z;
}
saveStrings("cmds.txt", output);
println("done!");
}
  }

Not sure what you mean with this. Your last code attempt doesn’t really explain what you want to do. Maybe you need to explain what you would like to do with this info. For instance, you get a value L which measures the length of the spiral to point x,y. In other words, you add the linear length of the spiral starting from the center, walking along the spiral until it gets to point x,y. Not sure at all where you are going with this tbh…

Kf

Yes, I want to get the length along the spiral to the locations of each black pixel in linear fashion.

There is a way to make this algorithm faster. i went for the trivial.

Kf



//===========================================================================
// FINAL FIELDS:
final int STEP_SIZE=2;

//===========================================================================
// GLOBAL VARIABLES:
int x, y, dx, dy, steps;
float theta;
PImage input;


//===========================================================================
// PROCESSING DEFAULT FUNCTIONS:

void settings() {
  size(500, 500);
}

void setup() {

  textAlign(CENTER, CENTER);
  rectMode(CENTER);
  imageMode(CENTER);

  x=0;
  y=0;
  steps=1;
  stroke(255);


  input=generateImage();

  input.resize(width, height);
  background(input);
  println(System.getProperty("file.encoding"));
}



void draw() {
  translate(width/2, height/2);
  //image(input,0,0);
  dx=int(cos(theta));
  dy=int(sin(theta));
  for (int i=0; i<steps; i++) {
    x+=dx;
    y+=dy;
    point(x, y);
  }
  steps=steps +STEP_SIZE;
  theta+=PI/2;

  if (theta>6.28) {
    theta=0;
  }
}

void keyReleased() {
}

void mouseReleased() {

  println("Length at " + (mouseX-width/2) + "," + (mouseY-height/2) + " is" + getLinearLength(mouseX, mouseY));
}



//===========================================================================
// OTHER FUNCTIONS:

PImage generateImage() {
  PImage img=createImage(width, height, ARGB);
  img.loadPixels();
  for (int i=0; i<width*height; i++) {
    int redVal=(int)map(i%width, 0, width, 0, 255);
    int greenVal=(int)map(i/height, 0, height, 0, 255);
    img.pixels[i]=color(redVal, greenVal, 50);
  }
  img.updatePixels();

  return img;
}

int getLinearLength(int x0, int y0) {
  

  int posx=0;
  int posy=0;
  int deltaX=0;
  int deltaY=0;
  float angle=0;
  int s=0;
  int sum=0;

  boolean intercept=false;

  x0=x0-width/2;
  y0=y0-height/2;



  while ( !intercept ) {  

    deltaX=int(cos(angle));
    deltaY=int(sin(angle));

    for (int i=0; i<s && !intercept; i++) {
      posx+=deltaX;
      posy+=deltaY;
      sum++;   

      if (dist(x0, y0, posx, posy) < STEP_SIZE) 
        intercept=true;
    } 

    //println(x0,y0,posx,posy);

    angle+=PI/2;
    s=s+STEP_SIZE;

    if (angle>6.28) {
      angle=0;
    }
  }

  return sum;
}

Update: I have the script generating a seemingly correct text data file with the positions of black pixels, but the second sketch to be used to recreate the image based on the text file data is not doing anything. Also, it runs extremely slow (1-5 minutes) which isn’t an issue but is annoying. Take a look please.

//float r = 0;
int z = 0;
float r = 0;
float theta = 0;
//float theta = 0;
PImage input;
String[] output;

void setup() {
  size(300, 300);
  background(255);
  output = new String[1];
  output[0] = "";
  selectInput("select an image to process", "select");
}
void select(File selection){
  if (selection == null){
    exit();
  }
  else {
    input = loadImage(selection.getAbsolutePath());
    input.resize(width, height);
    input.filter(THRESHOLD, 0.5);
    input.loadPixels();

//void draw() {
  while (z < 49950) {
  // Polar to Cartesian conversion
  float x = r * cos(theta);
  float y = r * sin(theta);

  
  int xx = int((x+width/2));
  int yy = int((y+height/2));
  if (z > 2000) {
  if(input.pixels[yy * width + xx] == color(0)) {
  //int pixelz = get(xx,yy);
  //if (pixelz == color(0)) {
    output[0] += z + "\n";
    println(z);
  //point(xx, yy);
  }
  }
  // Increment the angle
  theta += 0.01;
  // Increment the radius
  r += 0.003; //0.001 covers all pixels
  z = z + 1;
}
saveStrings("cmds.txt", output);
println("done!");
}
  }

Verifier / recreator:

String[] input;
float r = 0;
int z = 0;
float theta = 0;
int count = 0;
int pix;
void setup() {
  size(300,300);
  background(255);
  input = loadStrings("cmds.txt");
  loadPixels();
  while (z < 49950) {
    println(z);
    float x = r * cos(theta);
    float y = r * sin(theta);
    int xx = int((x+width/2));
    int yy = int((y+height/2));
    if (z > 2000) {
    for(int i = 0; i < input.length; i ++) {
     int pix = int(input[i]);
     if (z == pix) {
     point(xx,yy);
     }
     //theta += 0.01;
     //r += 0.003;
     //z = z +1;
    
    }
    }
    theta += 0.01;
     r += 0.003;
     z = z +1;
  }
  
  println("done");
}