View Javadoc

1   /**
2    * Copyright (c) 2011, The University of Southampton and the individual contributors.
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without modification,
6    * are permitted provided that the following conditions are met:
7    *
8    *   * 	Redistributions of source code must retain the above copyright notice,
9    * 	this list of conditions and the following disclaimer.
10   *
11   *   *	Redistributions in binary form must reproduce the above copyright notice,
12   * 	this list of conditions and the following disclaimer in the documentation
13   * 	and/or other materials provided with the distribution.
14   *
15   *   *	Neither the name of the University of Southampton nor the names of its
16   * 	contributors may be used to endorse or promote products derived from this
17   * 	software without specific prior written permission.
18   *
19   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26   * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29   */
30  package org.openimaj.image.feature.dense.binarypattern;
31  
32  import org.openimaj.citation.annotation.Reference;
33  import org.openimaj.citation.annotation.ReferenceType;
34  import org.openimaj.image.FImage;
35  import org.openimaj.image.analyser.ImageAnalyser;
36  import org.openimaj.image.pixel.Pixel;
37  
38  /**
39   * Implementation of an extended local binary pattern which has a
40   * variable number of samples taken from a variable sized circle
41   * about a point.
42   *  
43   * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
44   */
45  @Reference(
46  		type = ReferenceType.Article,
47  		author = { "Ojala, Timo", "Pietik\"{a}inen, Matti", "M\"{a}enp\"{a}\"{a}, Topi" },
48  		title = "Multiresolution Gray-Scale and Rotation Invariant Texture Classification with Local Binary Patterns",
49  		year = "2002",
50  		journal = "IEEE Trans. Pattern Anal. Mach. Intell.",
51  		pages = { "971", "", "987" },
52  		url = "http://dx.doi.org/10.1109/TPAMI.2002.1017623",
53  		month = "July",
54  		number = "7",
55  		publisher = "IEEE Computer Society",
56  		volume = "24",
57  		customData = {
58  			"date", "July 2002",
59  			"issn", "0162-8828",
60  			"numpages", "17",
61  			"doi", "10.1109/TPAMI.2002.1017623",
62  			"acmid", "628808",
63  			"address", "Washington, DC, USA"
64  		}
65  	)
66  public class ExtendedLocalBinaryPattern implements ImageAnalyser<FImage> {
67  	protected int[][] pattern;
68  	protected float radius;
69  	protected int samples;
70  	
71  	/**
72  	 * Construct an extended LBP extractor with the given parameters.
73  	 * @param radius the radius of the sampling circle
74  	 * @param samples the number of samples around the circle
75  	 */
76  	public ExtendedLocalBinaryPattern(float radius, int samples) {
77  		checkParams(radius, samples);
78  		this.radius = radius;
79  		this.samples = samples;
80  	}
81  	
82  	/**
83  	 * Calculate the LBP for every pixel in the image. The returned
84  	 * array of LBP codes hase the same dimensions as the image. 
85  	 * 
86  	 * Samples taken from outside the image bounds are assumed to have 
87  	 * the value 0.
88  	 * 
89  	 * @param image the image
90  	 * @param radius the radius of the sampling circle
91  	 * @param samples the number of samples around the circle
92  	 * @return a 2d-array of the LBP codes for every pixel
93  	 */
94  	public static int[][] calculateLBP(FImage image, float radius, int samples) {
95  		checkParams(radius, samples);
96  		
97  		int [][] pattern = new int[image.height][image.width];
98  		
99  		for (int y=0; y<image.height; y++) {
100 			for (int x=0; x<image.width; x++) {
101 				pattern[y][x] = calculateLBP(image, radius, samples, x, y);
102 			}
103 		}
104 		
105 		return pattern;
106 	}
107 	
108 	/**
109 	 * Calculate the extended LBP for a single point. The
110 	 * point must be within the image.
111 	 * 
112 	 * @param image the image
113 	 * @param radius the radius of the sampling circle
114 	 * @param samples the number of samples around the circle
115 	 * @param x the x-coordinate of the point
116 	 * @param y the y-coordinate of the point
117 	 * @return the LBP code
118 	 */
119 	public static int calculateLBP(FImage image, float radius, int samples, int x, int y) {
120 		float centre = image.pixels[y][x];
121 		int pattern = 0;
122 				
123 		for (int i=0; i<samples; i++) {
124 			double dx = -radius * Math.sin(2 * Math.PI * i / samples);
125 			double dy = radius * Math.cos(2 * Math.PI * i / samples);
126 			
127 			float pix = image.getPixelInterp(x+dx, y+dy);
128 			
129 			if (pix - centre >= 0) {
130 				pattern += Math.pow(2, i);
131 			}
132 		}
133 
134 		return pattern;
135 	}
136 
137 	/**
138 	 * Calculate the extended LBP for a single point. The
139 	 * point must be within the image.
140 	 * 
141 	 * @param image the image
142 	 * @param radius the radius of the sampling circle
143 	 * @param samples the number of samples around the circle
144 	 * @param point the point
145 	 * @return the LBP code
146 	 */
147 	public static int calculateLBP(FImage image, float radius, int samples, Pixel point) {
148 		return calculateLBP(image, radius, samples, point.x, point.y);
149 	}
150 
151 	private static void checkParams(float radius, int samples) {
152 		if (radius <= 0) {
153 			throw new IllegalArgumentException("radius must be greater than 0");
154 		}
155 		if (samples <= 1 || samples > 31) {
156 			throw new IllegalArgumentException("samples cannot be less than one or more than 31");
157 		}
158 	}
159 
160 	/* (non-Javadoc)
161 	 * @see org.openimaj.image.analyser.ImageAnalyser#analyseImage(org.openimaj.image.Image)
162 	 */
163 	@Override
164 	public void analyseImage(FImage image) {
165 		pattern = calculateLBP(image, radius, samples);
166 	}
167 	
168 	/**
169 	 * Get the pattern created during the last call to
170 	 * {@link #analyseImage(FImage)}.
171 	 * 
172 	 * @return the pattern
173 	 */
174 	public int[][] getPattern() {
175 		return pattern;
176 	}
177 }