jump to navigation

AFMA Best R&D Paper for Technology/Information Generation October 29, 2009

Posted by whaldsz in : news, projects, research , add a comment

Our study, “Development of a Computer Vision System for Milled Rice Quality Analysis” won the AFMA Best R&D Paper for Technology/Information Generation – Agriculture category.

The event was held during the 21st National Research Symposium last October 9, 2009 at the Fernando Lopez Hall of the Bureau of Soils and Water Management (BSWM) Bldg., Visayas Avenue, Diliman, Quezon City.

Check the full article @ http://www.bar.gov.ph/news/21stnrswinners.asp

Bookmark and Share

Background Subtraction in C# November 14, 2008

Posted by whaldsz in : emgu, how-to, projects, software , 19comments

I have been trying to learn OpenCV for a while now and I came across Emgu.CV, a C# wrapper.  Although the Emgu.CV is still under development, it has a many features that will make your work a lot easier if you’re doing a project in computer vision and image processing areas.  Some of its capabilities enable you to develop  web applications that can do processing of video and images via TCP/IP.

My goal in this article is to demonstrate simple background segmentation techniques using Emgu.CV.  Background segmentation is important if you are trying to extract features from an image and you want to remove or filter out unwanted objects.  You may also find this technique important when the recovery of color information from foreground objects is important.

Our objective is to remove the background from the rice image below. We want to get the color information from the rice kernels and be able to extract features for for each kernel, maybe for shape analysis or classification purposes.

Source code is available at the site.

Original image

I am sure there are other ways to perform background subtraction but this article will cover three methods that .

  1. Color filtering in Cielab color space
  2. Image masking (as i call it)
  3. Cielab + image masking

The three methods will be explained shortly and the link to the source code is available at the visioneer forum.

Color Filtering in Cielab Color Space

In this method, a copy of RGB image in Cielab space is obtained, and then process this image (in Cielab space) pixel by pixel.  Each pixel is checked if its color value is within specified range, otherwise, the pixel in the corresponding RGB image is set to black color.  An implementation is visible below:

   1: // background subtraction in cielab color space
   2: private void CielabColorFilteringBGSubtraction(string filename, bool displayResult)
   3: {
   4:     // create new image from file
   5:     Image<Bgr, Byte> rgbimage = new Image<Bgr, byte>(filename);
   6: 
   7:     // make a copy of the image in lab color space
   8:     Image<Lab, Byte> labimage = rgbimage.Convert<Lab, Byte>();
   9: 
  10:     // get the width and size
  11:     int width = labimage.Width;
  12:     int height = labimage.Height;
  13: 
  14:     // get the filter range for each channel in lab color space
  15:     IntRange l = new IntRange(Byte.Parse(min1TextBox.Text), Byte.Parse(max1TextBox.Text));
  16:     IntRange a = new IntRange(Byte.Parse(min2TextBox.Text), Byte.Parse(max2TextBox.Text));
  17:     IntRange b = new IntRange(Byte.Parse(min3TextBox.Text), Byte.Parse(max3TextBox.Text));
  18: 
  19:     // process each row in the image
  20:     for (int i = 0; i < width; i++)
  21:     {
  22:         // process each pixel
  23:         for (int j = 0; j < height; j++)
  24:         {
  25:             if (
  26:                 (labimage[j, i].X >=l.Max ) || (labimage[j, i].X <= l.Min) ||
  27:                  (labimage[j, i].Y >= a.Max) || (labimage[j, i].Y <= a.Min) ||
  28:                  (labimage[j, i].Z >= b.Max) || (labimage[j, i].Z <= b.Min)
  29:                 )
  30:             {
  31:                 // if outside the filter range, set the pixel to black color
  32:                 rgbimage[j, i] = new Bgr(0, 0, 0);
  33:             }
  34:         }
  35:     }
  36: 
  37:     // display
  38:     if (displayResult) this.NewImage("Cielab-based background segmented image", rgbimage);
  39: }

 

The resulting image looks like this.  In my PC, it took about 3.20 sec to perform background segmentation.

output

Image Masking

In this method, what we do is convert an RGB image into binary via binary thresholding.  (The choice of threshold value depends on the image, so you have to experiment on this.)  This binary image will serve as the mask image to copy pixels from the original image to the destination image, if the corresponding pixel in the mask image is nonzero. This is given by the following representation:

DestinatioImage(x,y) = SourceImage(x,y) if MaskImage(x,y) <> 0

where x and y is the pixel coordinates of the image. Source, destination and mask image have the same size.

Code implementation is as follows:

   1: // background subtraction by converting the RGB image to binary to create the mask
   2: // then use this mask to copy foreground objects in the image
   3: private void RGBImageMaskBGSubtraction(string filename, bool displayResult)
   4: {
   5:     // load the threshold value for grayscale image
   6:     double threshold = double.Parse(max2TextBox.Text);
   7: 
   8:     // create new image
   9:     Image<Bgr, Byte> img = new Image<Bgr, byte>(filename);
  10: 
  11:     //convert to grayscale
  12:     Image<Gray, Byte> gray = img.Convert<Gray, Byte>();
  13: 
  14:     //convert to binary image using the threshold
  15:     gray = gray.ThresholdBinary(new Gray(threshold), new Gray(255));
  16:
  17:     // copy pixels from the original image where pixels in 
  18:     // mask image is nonzero
  19:     Image<Bgr, Byte> newimg = img.Copy(gray);
  20: 
  21:     // display result
  22:     if (displayResult) this.NewImage("Background segmented", newimg);
  23: 
  24: }

 

One thing we should be aware of is that, all channels in RGB image is used to convert the image in grayscale image, then eventually binary image.  The output image is shown below:

output

Obviously, this is far worst then the first method.  But the advantage of segmentation using this technique is the speed.  The image was segmented for only 0.25 sec with more than 12X improvement, but we have to live with the quality. According to my tests, the performance improvement increases as the image size increased.  If we are very much concerned with the pixels in foreground objects, then the Image Masking method will not satisfy our requirements. 

However, there is another method to achieve the segmentation quality of cielab color filtering method, and the speed of the image masking method. 

Cielab + Image masking

In this method, we combine the first two techniques to get the cream of both ice creams. ;)   What we do is to perform the processing as in image masking method, but instead of using 3 channels (in RGB format) to convert the image to grayscale, we convert the image into Cielab space, select the a*-channel of the image, and use this channel to derive the mask image.

Code implementation here:

   1: // background subtraction by extracting one channel in cielab image to 
   2:  // create binary mask, and use this mask to copy foreground objects in 
   3:  // the original image
   4:  private void CielabChannelMaskBGSubtraction(string filename, bool displayResult)
   5:  {
   6:      double threshold = double.Parse(max2TextBox.Text);
   7: 
   8:      Image<Bgr, byte> rgb = new Image<Bgr, byte>(filename);
   9:      Image<Lab, Byte> img = rgb.Convert<Lab, Byte>();
  10: 
  11:      //get the a* channel 
  12:      Image<Gray, Byte> gray = img[channel];
  13: 
  14:      //threshold and invert
  15:      gray = gray.ThresholdBinary(new Gray(threshold), new Gray(255)).Not();
  16: 
  17:     // display the result
  18:      if (displayResult) this.NewImage("Background segmented", image);
  19:  }

 

Resulting output image here, note that it has almost the same quality as in the first method but with little performance penalty (processing takes around 0.03 sec longer than the second method).

output

Please note that you need to tweak the filter range(threshold value) for this to work in your problem area. Also,

  1. In Method 1, all three channels are used as filter ranges.
  2. Method 2, uses channel 1(maximum) for grayscale threshold value
  3. In method 3, you can select among the radio buttons (on the right) which channels to choose as the source for the mask image.  Then modify the filter range for that selected channel mask. You can also modify the source code to select one or more channels if it gives better performance.
  4. I have included two images located in the source code folder for testing purposes.

Screenshot is given below:

image

Bookmark and Share

How to Center MathType Equation in Microsoft Word September 24, 2008

Posted by whaldsz in : general, how-to, software , 4comments

Writing technical reports and papers for conference or journal publication can be a challenging task specially when it involves a lot of equations. This is also true for those who are doing their thesis and dissertation.  And sometimes centering an equation can be so frustrating. I myself, for one, have gone through this difficulty.

I’m using Microsoft Word 2003 with MathType 6.0.  What we want to achieve is to center the equation within the margin of our document and align the equation numbers[ e.g., (1), (2), and (3)] to the right edge of the margin as shown below:

image

Now, here’s how we do it:

1.  Make sure the STYLES AND FORMATTING is clicked so the pane at the right is visible (see the arrows).

image

2.  Once visible, the STYLES AND FORMATTING can be edited by clicking the MODIFY menu item in the drop-down menu:

image

3. A dialog box appears, click Format -> Tabs, make sure that you are editing the MTDisplayEquation style. See the example below.

image

4. Clicking the TABS menu item pops up another dialog box.  Assuming you are using A4-size paper with a left and right margin of 1.25″, you should edit the TAB STOP POSITION as shown, 0″ (left alignment),  3″ (center alignment) and 6 (right alignment).

image

5. Close the dialog boxes and try to insert an equation.  You should have the result as shown. Tab stops being pointed by arrows are now visible at the ruler area:

image

 

Bookmark and Share

Harnessing defocus blur to recover high-resolution information in shape-from-focus technique September 23, 2008

Posted by whaldsz in : research , add a comment

Traditional shape-from-focus (SFF) uses focus as the singular cue to derive the shape profile of a 3D object from a sequence of images. However, the stack of low-resolution (LR) observations is space-variantly blurred because of the finite depth of field of the camera. The authors propose to exploit the defocus information in the stack of LR images to obtain a super-resolved image as well as a high-resolution (HR) depth map of the underlying 3D object. Appropriate observation models are used to describe the image formation process in SFF. Local spatial dependencies of the intensities of pixels and their depth values are accounted for by modelling the HR image and the HR structure as independent Markov random fields. Taking as input the LR images from the stack and the LR depth map, the authors first obtain the super-resolved image of the 3D specimen and use it subsequently to reconstruct a HR depth profile of the object.

More: continued here

Bookmark and Share

Inferring Segmented Dense Motion Layers Using 5D Tensor Voting September 23, 2008

Posted by whaldsz in : research , add a comment

We present a novel local spatiotemporal approach to produce motion segmentation and dense temporal trajectories from an image sequence. A common representation of image sequences is a 3D spatiotemporal volume, (x,y,t), and its corresponding mathematical formalism is the fiber bundle. However, directly enforcing the spatiotemporal smoothness constraint is difficult in the fiber bundle representation. Thus, we convert the representation into a new 5D space (x,y,t,vx,vy) with an additional velocity domain, where each moving object produces a separate 3D smooth layer. The smoothness constraint is now enforced by extracting 3D layers using the tensor voting framework in a single step that solves both correspondence and segmentation simultaneously. Motion segmentation is achieved by identifying those layers, and the dense temporal trajectories are obtained by converting the layers back into the fiber bundle representation. We proceed to address three applications (tracking, mosaic, and 3D reconstruction) that are hard to solve from the video stream directly because of the segmentation and dense matching steps, but become straightforward with our framework. The approach does not make restrictive assumptions about the observed scene or camera motion and is therefore generally applicable. We present results on a number of data sets.

More: continued here

Bookmark and Share