LOW-HIGH tresholds

Hi,

I’m trying to make a two thresholds color analisis in a Pimage file.
But I can’t understand what I wrote wrong or If I made a conceptual mistake.

I’m a bit lost now.


 for(int i =0; i<imgOrigin.pixels.length; i++){
      
     if(imgOrigin.pixels[i] >= cpLow.getColorValue() && imgOrigin.pixels[i]<= cpHigh.getColorValue()){
     imgUpdated.pixels[i] = myred;
     println("Inside");
     }
     else{
      imgUpdated.pixels[i] = imgOrigin.pixels[i];
     
     }
    
       };

I can’t understand why when I move the blue and or green sliders
I can’t make the imgUpdated.pixels[i] = myred;
(I’m not interested in aplha value, so they will be always at 255 )

for instance with:
LOW: -16777216 = rgb = 0
HIGH: -16711936 = r =0 g =255 b=0

Theorically if in the image there are green values they will be red…
but it’s not like that at all.
Ok, there is something about using the “pure” values that is not very clear to me.
But anyway there are 65280 values from the low and the high so I should see something.
like the println(“Inside”);
or is just the file that is not optimal for this kind of analisis?!?!

here the code:


    
    PImage imgOrigin,imgUpdated;
    
    int low =0;
    int high = 0;
    
    
    color myred = color(255, 0, 0,255);
    
    void setup(){
      
      imgOrigin = loadImage("sunflower.jpg");  
      imgUpdated = createImage(imgOrigin.width,imgOrigin.height,RGB);
      size(400,400);  
    
    // load image onto surface - scale to the available width,height for display
    // so it's very stretchd
     image(imgOrigin, 0, 0, width, height);
    uiSetupColor();
    }

    
    void draw(){
   uiDraw();

        
       // We are going to look at both image's pixels
  imgOrigin.loadPixels();
  imgUpdated.loadPixels();
     
       for(int i =0; i<imgOrigin.pixels.length; i++){
      
     if(imgOrigin.pixels[i] >= cpLow.getColorValue() && imgOrigin.pixels[i]<= cpHigh.getColorValue()){
     imgUpdated.pixels[i] = myred;
     println("Inside");
     }
     else{
      imgUpdated.pixels[i] = imgOrigin.pixels[i];
     
     }
    
       };
       
    imgUpdated.updatePixels();
     
     image(imgUpdated, 0, 0, width, height);
     
      
     
    }


    void keyPressed(){

    if(key == 's' || key == 'S'){
      imgUpdated.save("trashold"+".jpg");
     println("Saved"); 
    }
    
    }

tab colorControl

import controlP5.*;

ControlP5 cp5;
ColorPicker cpLow,cpHigh; ;

void uiSetupColor() {
 
  cp5 = new ControlP5(this);
  
  cpLow = cp5.addColorPicker("low")
          .setPosition(20, 20)
          .setColorValue(color(0, 0, 0, 255))
          ;
          
 cpHigh  = cp5.addColorPicker("high")
          .setPosition(20, 100)
          .setColorValue(color(0, 0, 0, 255))
          ;
}

void  uiDraw(){
  println("LOW: "+cpLow.getColorValue() +" HIGH: " +cpHigh.getColorValue());
    //textSize(16);
    //text("Low: "+ cpLow.getColorValue(),20, 16);
    //text("High: "+ cpHigh.getColorValue(),20, 96);
    
}


public void controlEvent(ControlEvent c, ControlEvent d) {
  // when a value change from a ColorPicker is received, extract the ARGB values
  // from the controller's array value
  if(c.isFrom(cpLow)) {
    int r = int(c.getArrayValue(0));
    int g = int(c.getArrayValue(1));
    int b = int(c.getArrayValue(2));
    int a = int(c.getArrayValue(3));
    color col = color(r,g,b,a);
  
  }
  
    if(d.isFrom(cpHigh)) {
    int r = int(c.getArrayValue(0));
    int g = int(c.getArrayValue(1));
    int b = int(c.getArrayValue(2));
    int a = int(c.getArrayValue(3));
    color col = color(r,g,b,a);
    println("event \talpha:"+a+"\tred:"+r+"\tgreen:"+g+"\tblue:"+b+"\tcol_HIGH "+col);
  }
}

thanks
R_colors

1 Like

You are comparing a raw value. If you want to work with red colors, you should focus on the red component. However, you need to step back and consider working in HSB color mode instead of RGB and HSB mode might be more natural for this task. In plain words, RGB distributes the color in three components (hence RGB). In HSB, you will need to work with the hue component as it dictates the main color of interest. Hue will provide you the main color and you get tones by working with the saturation and brightness values.

If we were to stick to RGB, then I would use red() and I’d do the following:

float redLeft = red(imgOrigin.pixels[i]);
float redRight = red(cpLow.getColorValue());

if(redLeft >= redRight){
    ....here is the result based only on the red component
}

Note this applies only when working with single colors as in R-G-B. If you want to mix components, then you need to use dist() similar to finding the distance between two points in a 3D cartesian coordinate system. You setup your threshold based on Euclidean distances.

Kf

2 Likes

Thanks for your answer,
I’m sorry I was unclear using variable called myred, I should have called it showFiltered instead. I’m not intersted in red color, I used it just to have a graphical representation of which part of the image will be effected by the thresholds, my goal is just filtering the data.
I choosed red but that, was not the point.
I’m traing to understand how to filter part of the an image using raw color information, this sketch was just a simple display of the “selected/filtered” part, but there is something that is not working properly.

You can’t compare raw values like that because that isn’t how color is stored.

From a technical standpoint, colors are 32 bits of information ordered as AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB where the A’s contain the alpha value, the R’s are the red value, G’s are green, and B’s are blue. Each component is 8 bits (a number between 0 and 255). These values can be manipulated with bit shifting.

1 Like

All this question of color data arose from the fact that:
I’m trying to understand how Kim Asendorf worked on the ASDF Pixel Sort.
here: http://datamoshing.com/2016/06/16/how-to-glitch-images-using-pixel-sorting/

    /*
     ASDF Pixel Sort
     Kim Asendorf | 2010 | kimasendorf.com
     
     sorting modes
     
     0 = black
     1 = brightness
     2 = white
     
     */
    
    int mode = 0;
    
    // image path is relative to sketch directory
    PImage img;
    String imgFileName = "MyImage";
    String fileType = "jpgs";
    
    int loops = 1;
    
    // threshold values to determine sorting start and end pixels
    //looking for the red 255,0,0
    //-65536
    //red: 255.0 green: 0.0 blue: 0.0
    
    int blackValue = -1*256*1;
    
    
    //
    int row = 0;
    int column = 0;
    
    boolean saved = false;
    
    void setup() {
      img = loadImage("mycolorImage_4096.jpg");
      
      // use only numbers (not variables) for the size() command, Processing 3
      size(1, 1);
      
      // allow resize and update surface to image dimensions
      surface.setResizable(true);
      surface.setSize(img.width, img.height);
      
      // load image onto surface - scale to the available width,height for display
      image(img, 0, 0, width, height);
    }
    
    
    void draw() {
      
      // loop through columns
      while(column < img.width-1) {
    println("Sorting Column " + column);
    img.loadPixels(); 
    sortColumn();
    column++;
    img.updatePixels();
      }
      
      // loop through rows
      while(row < img.height-1) {
    println("Sorting Row " + column);
    img.loadPixels(); 
    sortRow();
    row++;
    img.updatePixels();
      }
      
      // load updated image onto surface and scale to fit the display width,height
      image(img, 0, 0, width, height);
      
      if(!saved && frameCount >= loops) {
    
      // save img
    img.save(imgFileName+"_"+mode+".png");
      
    saved = true;
    println("Saved "+frameCount+" Frame(s)");
    
    // exiting here can interrupt file save, wait for user to trigger exit
    println("Click or press any key to exit...");
      }
    }
    
    
    void sortRow() {
      // current row
      int y = row;
      
      // where to start sorting
      int x = 0;
      
      // where to stop sorting
      int xend = 0;
      
      while(xend < img.width-1) {
    
    x = getFirstNotBlackX(x, y);
    xend = getNextBlackX(x, y);
    
    
    
    if(x < 0) break;
    
    int sortLength = xend-x;
    
    color[] unsorted = new color[sortLength];
    color[] sorted = new color[sortLength];
    
    for(int i=0; i<sortLength; i++) {
      unsorted[i] = img.pixels[x + i + y * img.width];
    }
    
    sorted = sort(unsorted);
    
    for(int i=0; i<sortLength; i++) {
      img.pixels[x + i + y * img.width] = sorted[i];  
    }
    
    x = xend+1;
      }
    }
    
    
    void sortColumn() {
      // current column
      int x = column;
      
      // where to start sorting
      int y = 0;
      
      // where to stop sorting
      int yend = 0;
      
      while(yend < img.height-1) {
    
    
    y = getFirstNotBlackY(x, y);
    yend = getNextBlackY(x, y);
    
    
    if(y < 0) break;
    
    int sortLength = yend-y;
    
    color[] unsorted = new color[sortLength];
    color[] sorted = new color[sortLength];
    
    for(int i=0; i<sortLength; i++) {
      unsorted[i] = img.pixels[x + (y+i) * img.width];
    }
    
    sorted = sort(unsorted);
    
    for(int i=0; i<sortLength; i++) {
      img.pixels[x + (y+i) * img.width] = sorted[i];
    }
    
    y = yend+1;
      }
    }
    
    
    // black x
    int getFirstNotBlackX(int x, int y) {
      
      while(img.pixels[x + y * img.width] < blackValue) {
    x++;
    if(x >= img.width) 
      return -1;
      }
      
      return x;
    }
    
    int getNextBlackX(int x, int y) {
      x++;
      
      while(img.pixels[x + y * img.width] > blackValue) {
    x++;
    if(x >= img.width) 
      return img.width-1;
      }
      // esc
      return x-1;
    }
    
    
    // black y
    int getFirstNotBlackY(int x, int y) {
    
      if(y < img.height) {
    while(img.pixels[x + y * img.width] < blackValue) {
      y++;
      if(y >= img.height)
    return -1;
    }
      }
      
      return y;
    }
    
    int getNextBlackY(int x, int y) {
      y++;
    
      if(y < img.height) {
    while(img.pixels[x + y * img.width] > blackValue) {
      y++;
      if(y >= img.height)
    return img.height-1;
    }
      }
      
      return y-1;
    }

he used color var blackValue to set the threshold,
but I can’t understand why… he decided that number specifically to be “black”
Obviously it’s a very bright green.

// threshold values to determine sorting start and end pixels

int blackValue = -16000000;

//what is blackValue?? 
// RawToRGBA_HSB

    int blackValue =-16000000  ;
    println(blackValue);
    noStroke();
    fill(blackValue);
    rect(0,0,100,100);
    
    float r =red(blackValue);
    float g =green(blackValue);
    float b =blue(blackValue);
    float a =alpha(blackValue);
    println("red: "+r+" green: "+g+" blue: "+b);
    
    float h= hue(blackValue);
    float s = saturation(blackValue);
    float br = brightness(blackValue);
    //println("hue: "+h+" saturation: "+s+" brightness: "+br);

ASDF reduced, only Mode 0:

In mode 0, or black mode, the script will begin sorting when it finds a pixel which is not black in the column or row, and will stop sorting when it finds a black pixel. The script identifies black pixels by comparing the pixel’s color value to a threshold, if it’s lower than the black threshold the pixel is deemed to not be black, if it’s higher it’s deemed to be black. You can adjust this threshold by changing the blackValue variable which is by default set to -16.000.000

like I said it’s everithing, but not black…
and like Jeremy wrote… to compare raw colors data
it’s not the best way to think about colors.

if I make an image of 4096*4096 and I fill every .pixels[]
with the numbers in between:
-1 this is White
-16 777 216 this is Black
I get this color structure…

https://processing.org/tutorials/color/
We will use eight bit color for our grayscale range and 24 bit for full color (eight bits for each of the red, green, and blue color components).

Behind the scenes in the computer’s memory, color is always talked about as a series of 24 bits (or 32 in the case of colors with an alpha)

anyway, now it’s quite clear what the raw colors data represent.

for instance:

if I want to make green 254
RAW: - 512 or 1* 256 * -256
red: 255.0 green: 254.0 blue: 0.0

RAW: 256256-256 = -16777216
red: 0.0 green: 0.0 blue: 0.0

and so on…

My idea was just to see if it was possible to choose a color starting point for the sorting and to see all the colors that will be the starting points, before lanching the script…
Or to modify fhe functions to work only on specific colors using thresholds…
Anyway I understood that I have to think in a different way.

Thank you.

The only reason to manipulate channels in this way – as opposed to color(0, 254, 0) – is speed. And if you actually want speed, use bit shifting, as linked in the color datatype reference. There are also examples of bit shifting listed under red(), green(), and blue() in the reference.

2 Likes

4 posts were split to a new topic: N-dimensional sorting and color