Sunday, March 13, 2011

ImageJ 2: Invert an image

เรายังอยู่ที่การ invert image ครับ แต่จะลองใช้เทคนิคในการเข้าถึงพิกเซลต่างๆกัน ลองดูตัวอย่างโคัดครับ ในที่นี้มีอย่างน้อย 4 วิธี ดูรายละเอียดตามที่หมายเหตุได้ครับ

//Plugin to invert a grayscale image
import ij.ImagePlus;
import ij.plugin.filter.PlugInFilter;
import ij.process.ImageProcessor;
import ij.process.ByteProcessor;

// _ in the class name = plugin
public class My_Invert implements PlugInFilter 
{
 public int setup(String arg, ImagePlus im) 
 {
  return DOES_8G;  //accept only 8-bit grayscale image
 }

 public void run(ImageProcessor ip) 
 {  
  //1. use getPixel, putPixel to access each pixel
  //they check image boundary+invoke function call, slowest
  int w = ip.getWidth();
  int h = ip.getHeight();
  //for each pixel
  for(int x=0;x<w;x++)
   for(int y=0;y<h;y++)
    ip.putPixel(x,y,255-ip.getPixel(x,y));
    
  /*
  //2. use get,set which do not check boundary
  //still invoke function, faster
  int w = ip.getWidth();
  int h = ip.getHeight();
  //for each pixel
  for(int x=0;x<w;x++)
   for(int y=0;y<h;y++)
    ip.set(x,y,255-ip.get(x,y));
  */
  
  /*  
  //3. use get,set with 1d indices
  //only 1 loop, invoke function, more faster
  int MN = ip.getPixelCount(); //total pixels
  for(int p=0;p<MN;p++)
   ip.set(p, 255-ip.get(p));
  */
  
  /*
  //4. use getPixels to directly process pixel array
  //direct access, no function invocation
  //fastest but more memory need
  //check if ip is ByteProcessor (0-255)
  if(!(ip instanceof ByteProcessor))
   return;
  if(!(ip.getPixels() instanceof byte[]))
   return;
  //dump to array but by reference!!!
  byte[] pixels = (byte[]) ip.getPixels(); 
  int MN = ip.getPixelCount();
  for(int p=0;p<MN;p++)
  {
   int v = 0xFF & pixels[p]; //convert to integer
   v = 255-v;
   pixels[p] = (byte) (0xFF & v); //to byte
  }
  */      
 }
}

ตามทฤษฎีแล้วแต่ละวิธีจะให้ความเร็วต่างกัน ซึ่งจะเห็นชัดขึ้นเมื่อรูปมีขนาดใหญ่ขึ้นครับ

No comments:

Post a Comment