Get center pixel and apply color to the entire row of pixels

edited March 2014 in How To...

Continuing from the knowledge gained from someone who answered a previous question I posted earlier today...

I am trying to write a sketch that will take the center pixel from each row of a webcam feed and apply that color to the entire row. So far everything I have tried, I have only been able to get the top row of pixels to change or nothing. Can someone please help me figure this out? [-O<

This is where I am at right now and I feel like this is in the right direction in terms of thought, but it's not changing anything.

I will just show the for-loop business I have going on:

loadPixels();

for (int x = 0; x < feed.width; x++){
  // Calculate the difference between x and the end of the row
  int difference = (x + feed.width) - x;

  for (int y = 0; y < feed.height; y++){
    // If this is true, then that is a center pixel
    if (difference == feed.width / 2){ 
      int loc = x + y * feed.width; // Get location of pixel
      pixels[y] = pixels[loc]; // Change color to "center pixel"
    }    
  }
}

updatePixels();

Answers

  • edited March 2014 Answer ✓

    I don't have a cam nor can run your code. :-&
    Nevertheless, using my own tips from the other post, I've come up w/ this untested algorithm: %%-

    // forum.processing.org/two/discussion/4013/
    // get-center-pixel-and-apply-color-to-the-entire-row-of-pixels
    
    import processing.video.*;
    Capture feed;
    
    void setup() {
      size(300, 200);
      frameRate(30);
    
      (feed = new Capture(this, width, height, 30)).start();
    }
    
    void draw() {
      if (!feed.available())  return;
    
      feed.read();
      changeImage(feed);
      set(0, 0, feed);
    }
    
    static final void changeImage(PImage img) {
      img.loadPixels();
    
      final color[] dots = img.pixels;
      final int w = img.width, h = img.height, cx = w>>1;
    
      for (int row = 0; row != h;) {
        final int rw  = row++ * w;
        final color c = dots[rw + cx];
    
        for (int col = w + rw; col-- != rw; dots[col] = c);
      }
    
      img.updatePixels();
    }
    
  • Wow, that's some syntax I have never even seen before with for-loops!

    But when trying to test your algorithm I am met with this message:

    ** (Processing core video:172): WARNING **: ColorConverter: size 121600 is not a multiple of unit size 120000

    with no sign of a feed being streamed. :(

  • I've applied it to my original sketch, and it now works! :) Thank you GoToLoop! Could you perhaps explain what is going on in the for-loops?

    import processing.video.*;
    
    Capture feed; // webcam
    
    int rw;
    int w;
    int h;
    int cx;
    
    color c; // center pixel color
    
    void setup(){
    
      size(displayWidth, displayHeight);
    
      feed = new Capture(this, displayWidth, displayHeight);  
      feed.start();
    
      w = feed.width;
      h = feed.height;
      cx = w >> 1;
    }
    
    void draw(){
      if (feed.available() == true){
        feed.read();
      }
      else{
        return;
      }
    
      image(feed, 0, 0);
      loadPixels();
    
      for (int row = 0; row != h;){
        rw = row++ * w;
        c = pixels[rw + cx];
    
        for (int col = w + rw; col-- != rw; pixels[col] = c);
      }  
      updatePixels();
    }
    
  • edited March 2014 Answer ✓

    Could you perhaps explain what is going on in the for-loops?

    Well, you haven't pin-pointed exactly where you don't understand. I guess I'll have to explain line by line then! (:|

    @ #33 -> We're gonna need to treat the 1D pixels[] array as if it were a 2D [y][x] 1!
    Even though it's a linear array, if we know the width of the image it represents, we can consider that each width chunk is a full row!
    So if we want row or y = 10 & column or x = 25, we multiply 10 * img.width.
    After that, we add 25 in order to get the final 1D position which represents the (row,col) 2D coords.

    @ #35 -> Iterator row represents the y coord.

    @ #36 -> Besides incrementing the iterator, that multiplication represents the 0th column or x of the current row or y.
    Caching the result in rw too. No need to keep doing it over and over in the next inner loop!

    @ #37 -> Variable cx is half the width of the image. It's both its radius & center x position within a row or y.
    By adding rw to cx, we get the center x of current row! Then we get the color value of that position and cache it in c.

    @ #39 -> Perhaps that's what's confusing you: it's a backwards loop. Rather than starting at the beginning, it starts at the end!
    So, w + rw is the last column + 1 of current row or y. Whereas rw alone alone is the 0th column position!
    In the end, all that row gets the color c, which is the color of its center! (*)

    Comparing backwards loop to regular forward loop: :-j

    for (int col = w + rw; col-- != rw; pixels[col] = c);

    for (int col = rw, end = w + rw; col != end; pixels[col++] = c);

Sign In or Register to comment.