Image Processing

edited August 2015 in How To...

Hi, I just started to learn Processing because I need to do some stuffs. I went thru some tutorials about "Images and Pixels" but there is only some basic code how to load and process image and pixels. My question is, there is an example where I can find how to process a image with an exact formula ? what i mean is to load a image, process the image thru a formula and have a output of the loaded image but changed (in a 2nd window "right to the 1st image") with the processed image (formula).

Answers

  • In order to get an independent copy of a PImage, we can use its get() method:
    http://processing.org/reference/PImage_get_.html

  • I understand the copy of an image but what i really mean is to just get the out put of the basic image that will be processed thru a formula and we gonna have a output. example: EXZYVETo We load a main/basic image "left" we process it thru e formula and we get the results to the right. That's my question, is there an example where i can learn how to process the image with a mathematical formula and get the results?

  • edited August 2015

    here is an example

    // have "apples.jpg" in the sketchs data folder 
    // see http : // www.processing.org/reference/loadPixels_.html etc. 
    
    PImage myImage1, myImage2;  // source and destiny image
    
    void setup() {
    
      size(1100, 660); 
    
      // load it 
      myImage1 = loadImage("apples.jpg");
      // delay(111);
      // myImage1.resize(400, 0);
      int halfImage = myImage1.width*myImage1.height/2;
    
      // make a copy 
      myImage2 = myImage1.get();  
      //
      // change the copy 
      myImage1.loadPixels();
      myImage2.loadPixels();
    
      // some changes - what we need here
      // we copy half of the image to the other
      for (int i = 0; i < halfImage; i++) {
        // copy upper half into lower half     
        myImage2.pixels[i+halfImage] = myImage1.pixels[i];
        // make pretty red pixels white 
        if (red(myImage1.pixels[i])>240) {
          myImage2.pixels[i+halfImage] = color(255);
        }
      }
      myImage2.updatePixels();
      noLoop();
    } // func 
    
    void draw () {
      image(myImage1, 10, 10);
      image(myImage2, myImage1.width+20, 10);
    }
    //
    
  • Here is another example.

    In this picture the top picture is the origina; and the bottom picture is a processed copy. The ARGB channels of the original have been moved into AGBR order.

    dest

    PImage src, dest;
    
    public void setup(){
      size(350,360);
      src = loadImage("car1.jpg");
      // Quick way to get an image of the same size
      dest = src.get();
      // Show original
      image(src,10,10);
      // Process image
      processImage(src, dest);
      image(dest,10,200);
    }
    
    public void processImage(PImage s, PImage d){
      s.loadPixels();
      d.loadPixels();
      int[] sp = s.pixels;
      int[] dp = d.pixels;
      for(int i = 0; i < sp.length; i++){
        // Extract the alpha, red, green and blue componets for
        // this pixel each component will be in the range 0 -255
        int a = (sp[i] >> 24) & 0xff;
        int r = (sp[i] >> 16) & 0xff;
        int g = (sp[i] >> 8) & 0xff;
        int b = sp[i] & 0xff;
        // Now process the pixel by swapping the RGB channels arround
        // 
        int newCol = (a << 24) | (g << 16) | (b << 8) | r;
        dp[i] = newCol;
      }
      d.updatePixels();
    }
    
  • That's helpful but I'm talking about formulas, Gaussian filter, Zonal high pass filter, Butterworth low pass filter, Cos Transform, Homomorphic filtering ....etc

    What you saw me there is just manual code, but what i'm talking is formulas, to change a picture with an exact formula.

  • @Domino60, you don't say what you want exactly. You just give some vague examples.

    And we don't know your skill level.

    You've been given some examples and you can work with them.

    quark provided a formula.

    just use his code, implement your formula in it and come back when you have a concrete problem with your own code you show us then.

    ;-)

  • AFAIK the filters you mentioned don't have an exact mathematical formula, rather they are an algorithm that manipulates the pixel colour data. In my code you simply replace line 29 with code that performs the algorithm.

  • Moved out of Questions about Code, because you don't give any code.

    You mention a number of algorithms. That's the starting point for some Web searches, no? The answers above give a framework for testing these algorithms.

  • quark

    You said that in your code i just change the line 29 with my exact formula. Am i right?

  • To reiterate this again: You're not being clear. We don't know what you mean by a "formula", and honestly, I don't think you know what you mean by it either.

    What do you mean? What does your "formula" actually do to the image?

  • I know what exactly I mean. A mathermatical formula which change the state of each pixel in the image and at the end we got the full picture changed.

    For example the Gaussian filter:

    I got a mathematical formula which act exactly as in the picture, what i need it to "somehow" place that mathematical formula to change each pixel from the image one by one so in the end i got the changed image.

  • Hello,

    sorry for having been rude.

    you wrote:

    what i need it to "somehow" place that mathematical formula to change each pixel from the image one by one so in the end i got the changed image.

    but that's exactly what happens in the code quark has provided. Get the original pixel, change it (famous line 29), write it back.

    Of course you have to translate your formula into the processing language to make it work.

    And it won't look the same then. Maybe it isn't on one line even but two or three lines. But your code works on the principle of the formula then.

    That's what programming is all about: Translating mathematical formulas or every day concepts (play chess, sort a list) into code that can be executed by a computer

    Can you post your formula please?

    Then we can translate it to processing code.

    When you have different formulas, the user could choose from them and the image looks different each time.

    Best,

    Chrisir ;-)

  • edited August 2015

    have you read this? it goes into image processing using Processing (the software):

    https://processing.org/tutorials/pixels/

    most non-trivial image processing acts on a 'kernel' of pixels at once rather than an individual pixel. it runs these through a convolution matrix and saves the result. (see Level II: Pixel Group Processing in the above tutorial)

    but, yes, post the formula

  • see, the wikipedia entry for Guassian blur gives you a convolution matrix

    https://en.wikipedia.org/wiki/Gaussian_blur#Sample_Gaussian_matrix

    it's 7x7 so a lot bigger then the one in the tutorial, but the idea is the same.

  • edited August 2015

    Of course you have to translate your formula into the processing language to make it work.

    And it won't look the same then. Maybe it isn't on one line even but two or three lines. But your code works on the principle of the formula then.

    Hi, thanks for understanding what i need, I'm new to processing so I'm not an expect with image processing, i need some time to understand what's going on, yes i understood the quarks code that in the line 29 i change each pixel and as you said i need to translate the mathematical formula in to processing code, but is there a way to put the exact formula in the code?

    I'm working on a project and the person who i give the project he needs to see the exact formula in the code. He don't know anything about the code but he needs to see the formula "in the code" i know it's different in each programming language but is that possible with processing?

    I got this from C coding:

    s1+=getpixel(j,k)*(j,k)+((cos(3.14/N)+(u*j+1/2)))*(cos(3.14/n)*(v*k+1.2));
    

    This is as example, in C is different, you need to get the array of pixels and put them in the formula and run them for each pixel a time in a huge code of For's. As i saw in processing here is easier with pixels that's why i wanna try here.

  • post your formula

    there is QScript which works with formulas

    i am not sure it works on pixels though

    (or explain the guy that programming is always translating and not plain formula...)

  • Can you give me an example how to translate the formula into code and changing each pixel. And what's the QScript?

  • Do you mean the C code formula?

  • Well if you can, but at least an example so i could orientate by it and "translate" myself to code.

  • you see 2 examples above

    the C code is without context, I can't see u n v k

  • I can see only changing the RGB of each pixel but not actually using a math. formula.

  • that's a formula written in a programming language

    you are a little stubborn here...

  • edited August 2015

    ah, here is a full JAVA program on Gaussian

    (not for processing)

    /**
    ** Copyright 2005 Huxtable.com. All rights reserved.
     */
    
    package com.jhlabs.image;
    
    import java.awt.image.*;
    
    /**
     * A filter which applies Gaussian blur to an image. This is a subclass of ConvolveFilter
     * which simply creates a kernel with a Gaussian distribution for blurring.
     * @author Jerry Huxtable
     */
    public class GaussianFilter extends ConvolveFilter {
    
      static final long serialVersionUID = 5377089073023183684L;
    
      protected float radius;
      protected Kernel kernel;
    
      /**
         * Construct a Gaussian filter
         */
      public GaussianFilter() {
        this(2);
      }
    
      /**
         * Construct a Gaussian filter
         * @param radius blur radius in pixels
         */
      public GaussianFilter(float radius) {
        setRadius(radius);
      }
    
      /**
         * Set the radius of the kernel, and hence the amount of blur. The bigger the radius, the longer this filter will take.
         * @param radius the radius of the blur in pixels.
         */
      public void setRadius(float radius) {
        this.radius = radius;
        kernel = makeKernel(radius);
      }
    
      /**
         * Get the radius of the kernel.
         * @return the radius
         */
      public float getRadius() {
        return radius;
      }
    
      public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
        int width = src.getWidth();
        int height = src.getHeight();
    
        if ( dst == null )
          dst = createCompatibleDestImage( src, null );
    
        int[] inPixels = new int[width*height];
        int[] outPixels = new int[width*height];
        src.getRGB( 0, 0, width, height, inPixels, 0, width );
    
        convolveAndTranspose(kernel, inPixels, outPixels, width, height, alpha, CLAMP_EDGES);
        convolveAndTranspose(kernel, outPixels, inPixels, height, width, alpha, CLAMP_EDGES);
    
        dst.setRGB( 0, 0, width, height, inPixels, 0, width );
        return dst;
      }
    
      public static void convolveAndTranspose(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, boolean alpha, int edgeAction) {
        float[] matrix = kernel.getKernelData( null );
        int cols = kernel.getWidth();
        int cols2 = cols/2;
    
        for (int y = 0; y < height; y++) {
          int index = y;
          int ioffset = y*width;
          for (int x = 0; x < width; x++) {
            float r = 0, g = 0, b = 0, a = 0;
            int moffset = cols2;
            for (int col = -cols2; col <= cols2; col++) {
              float f = matrix[moffset+col];
    
              if (f != 0) {
                int ix = x+col;
                if ( ix < 0 ) {
                  if ( edgeAction == CLAMP_EDGES )
                    ix = 0;
                  else if ( edgeAction == WRAP_EDGES )
                    ix = (x+width) % width;
                } else if ( ix >= width) {
                  if ( edgeAction == CLAMP_EDGES )
                    ix = width-1;
                  else if ( edgeAction == WRAP_EDGES )
                    ix = (x+width) % width;
                }
                int rgb = inPixels[ioffset+ix];
                a += f * ((rgb >> 24) & 0xff);
                r += f * ((rgb >> 16) & 0xff);
                g += f * ((rgb >> 8) & 0xff);
                b += f * (rgb & 0xff);
              }
            }
            int ia = alpha ? PixelUtils.clamp((int)(a+0.5)) : 0xff;
            int ir = PixelUtils.clamp((int)(r+0.5));
            int ig = PixelUtils.clamp((int)(g+0.5));
            int ib = PixelUtils.clamp((int)(b+0.5));
            outPixels[index] = (ia << 24) | (ir << 16) | (ig << 8) | ib;
            index += height;
          }
        }
      }
    
      /**
         * Make a Gaussian blur kernel.
         */
      public static Kernel makeKernel(float radius) {
        int r = (int)Math.ceil(radius);
        int rows = r*2+1;
        float[] matrix = new float[rows];
        float sigma = radius/3;
        float sigma22 = 2*sigma*sigma;
        float sigmaPi2 = 2*ImageMath.PI*sigma;
        float sqrtSigmaPi2 = (float)Math.sqrt(sigmaPi2);
        float radius2 = radius*radius;
        float total = 0;
        int index = 0;
        for (int row = -r; row <= r; row++) {
          float distance = row*row;
          if (distance > radius2)
            matrix[index] = 0;
          else
            matrix[index] = (float)Math.exp(-(distance)/sigma22) / sqrtSigmaPi2;
          total += matrix[index];
          index++;
        }
        for (int i = 0; i < rows; i++)
          matrix[i] /= total;
    
        return new Kernel(rows, 1, matrix);
      }
    
      public String toString() {
        return "Blur/Gaussian Blur...";
      }
    }
    
  • We need more context surrounding the formula you have posted. We do not know what the values/meaning of the variables j, u, n, N, v, or k in the formula stand for or represent.

  • this is a processing example what runs kind of

    but doesn't give good results

    it is based on quark and also the website stated:

    // http : // blog.ivank.net/fastest-gaussian-blur.html
    
    // GAUSSIAN ----  
    
    PImage src, dest;
    
    public void setup() {
      size(650, 360);
      src = loadImage("car1.jpg");
      // Quick way to get an image of the same size
      dest = src.get();
      // Show original
      image(src, 10, 10);
      // Process image
      processImage(src, dest);
      image(dest, 10, 200);
    }
    
    public void processImage(PImage s, PImage d) {
      s.loadPixels(); // src
      d.loadPixels(); // dest 
      int[] sp = s.pixels; // src pixels 
      int[] dp = d.pixels; // dest pixels 
      //
      gaussBlur_1 (sp, dp, src.width, src.height, .4); 
    
      //  for (int i = 0; i < sp.length; i++) {
      //    // Extract the red, green and blue componets for
      //    // this pixel. 
      //    // each component will be in the range 0 to 255
      //
      //    // this is rgb
      //    float r = red(sp[i]);
      //    float g = green(sp[i]);
      //    float b = blue(sp[i]);
      //    // 
      //    // Now process the pixel by changing the RGB channels 
      //    // this is changing green and blue
      //    int newCol = color (r, g*0.3, b*3.0);
      //    // this rbg
      //    // int newCol = color (r, b, g);
      //    dp[i] = newCol;
      //  }
      d.updatePixels();
    }
    
    // source channel, target channel, width, height, radius
    void gaussBlur_1 (int[] scl, int[] tcl, int w, int h, float r) {
      int rs = int(ceil(r * 2.57));     // significant radius
      for (int i=0; i<h; i++)
        for (int j=0; j<w; j++) {
          float val = 0, wsum = 0;
          for (int iy = i-rs; iy<i+rs+1; iy++)
            for (int ix = j-rs; ix<j+rs+1; ix++) {
              int x = int( min(w-1, max(0, ix)));
              int y = int( min(h-1, max(0, iy)));
              float dsq = (ix-j)*(ix-j)+(iy-i)*(iy-i);
              double wght = Math.exp( -dsq / (2*r*r) ) / (Math.PI*2*r*r);
              val += scl[y*w+x] * wght;  
              wsum += wght;
            }
          tcl[i*w+j] = Math.round(val/wsum);
        }
    }
    //
    
  • edited August 2015

    it's not a algorithm based on one pixel alone like with quarks example

    you can't get rid of the for-loops, because the principle of Gaussian is kind of to compare each pixel to the neighbours in a radius I think

    therefore you need a lot of for-loops and stuff going on

    (which I messed up to get it running, hence the results are so wrong)

  • edited August 2015

    Slightly tweak over @Chrisir's gaussBlur_1(): :ar!

    static final PImage gaussBlur(PImage scr, PImage dst, float r) {
      if (scr == null || scr.width <= 0 || scr.height <= 0)  return null;
    
      final int rs = ceil((r = abs(r)) * 2.57);
      final float rad2Sq = 2*r*r;
    
      final int w = scr.width, h = scr.height;
      if (dst == null || dst.width != w || dst.height != h)  dst = scr.get();
    
      scr.loadPixels();
      dst.loadPixels();
      final color[] sp = scr.pixels, dp = dst.pixels;
    
      for (int irs = rs, i = 0; i < h; ++i, ++irs)
        for (int jrs = rs, j = 0; j < w; ++j, ++jrs) {
          float vals = 0, wsum = 0;
    
          for (int iy = i - rs; iy <= irs; ++iy) {
            final int yw = constrain(iy, 0, h - 1) * w;
    
            for (int ix = j - rs; ix <= jrs; ++ix) {
              final int x = constrain(ix, 0, w - 1);
              final float dsq  = sq(ix - j) + sq(iy - i);
              final float wght = exp(-dsq/rad2Sq) / (PI*rad2Sq);
    
              vals += wght * sp[yw + x];
              wsum += wght;
            }
          }
    
          dp[i*w + j] = round(vals/wsum);
        }
    
      dst.updatePixels();
      return dst;
    }
    
  • I have closed this discussion because the OP has started a new one on the same topic here

This discussion has been closed.