package de.tud.inf.operator.fingerprints.lbp; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; import com.rapidminer.example.Attribute; import com.rapidminer.example.Example; import com.rapidminer.example.ExampleSet; import com.rapidminer.example.table.AttributeFactory; import com.rapidminer.example.table.DataRow; import com.rapidminer.example.table.DataRowFactory; import com.rapidminer.example.table.MemoryExampleTable; import com.rapidminer.operator.IOObject; import com.rapidminer.operator.Operator; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; import com.rapidminer.parameter.ParameterType; import com.rapidminer.parameter.ParameterTypeBoolean; import com.rapidminer.parameter.ParameterTypeCategory; import com.rapidminer.parameter.ParameterTypeInt; import com.rapidminer.parameter.ParameterTypeString; import com.rapidminer.tools.Ontology; import de.tud.inf.example.set.ComplexExampleSet; import de.tud.inf.example.set.attributevalues.ComplexValueFactory; import de.tud.inf.example.set.attributevalues.DataMapValue; import de.tud.inf.example.set.attributevalues.MapValue; import de.tud.inf.example.table.ComplexAttribute; import de.tud.inf.example.table.MapAttribute; import de.tud.inf.operator.capabilites.Capability; import de.tud.inf.operator.capabilites.CapabilityBuilder; public class LocalBinaryPattern extends Operator { public static final String PARAMETER_MAP_NAME = "map_attribute_name"; public LocalBinaryPattern(OperatorDescription description) { super(description); } @Override public IOObject[] apply() throws OperatorException { ExampleSet output = null; Map<Integer, Integer> map = null; try { ComplexExampleSet inputSet = getInput(ComplexExampleSet.class); MapValue mv = null; MapAttribute mapAttr = (MapAttribute) inputSet.getAttributes().get(getParameterAsString(PARAMETER_MAP_NAME)); Iterator<Example> it = inputSet.iterator(); Example e; DataMapValue dmValue = (DataMapValue)ComplexValueFactory.getComplexValueFunction(Ontology.DATA_MAP,""); while (it.hasNext()) { e = it.next(); mv = e.getMapValue(mapAttr); // calculate x and y size (map sorted by x,y) //nr of x values int xSize = mv.getDimension()[0]; //nr of y values int ySize = mv.getDimension()[1]; // count symbols int radius = getParameterAsInt("radius"); int numberOfPoints = getParameterAsInt("points"); int nrow = xSize; int ncol = ySize; map = new TreeMap<Integer, Integer>(); for (int i=0; i<=nrow-(2*radius+1); i++) { for (int j=0; j<=ncol-(2*radius+1); j++) { int k = i + radius; int l = j + radius; double[] points = getCircle(mv, k, l, radius, (double) numberOfPoints); int result = 0; for (int a=0; a<points.length; a++) result = (int) (result + (Math.pow(2,a)* ((points[a] >= mv.getValueAtId(k,l))?1:0))); // rotate if (getParameterAsInt("rotation") == 1) { for (int m=1; m<points.length; m++) { int r = 0; for (int a=0; a<points.length; a++) r = (int) (r + (Math.pow(2,a) * ((points[(a+m) % points.length] >= mv.getValueAtId(k,l))?1:0))); if (r < result) result = r; } } Integer number; if ((number = map.get(result)) != null) { number++; map.put(result, number); } else map.put(result, 1); } } // normalize double totalNum = ((xSize - (2*radius+1)) + 1) * ((ySize - (2*radius+1)) + 1); // create output map, here we do not have string keys Map<Integer, Double> resultMap = new HashMap<Integer,Double>(); for (Map.Entry<Integer, Integer> mapEntry: map.entrySet()) { if (getParameterAsBoolean("normalize")) resultMap.put(mapEntry.getKey(), mapEntry.getValue()/totalNum); else resultMap.put(mapEntry.getKey(), mapEntry.getValue().doubleValue()); } dmValue.setMap(resultMap); // create output example set List<Attribute> attributeList = new ArrayList<Attribute>(1); ComplexAttribute lnfAttribute = (ComplexAttribute)AttributeFactory.createAttribute("LBP", Ontology.DATA_MAP); attributeList.add(lnfAttribute); MemoryExampleTable exampleTable = new MemoryExampleTable(attributeList); DataRowFactory factory = new DataRowFactory(DataRowFactory.TYPE_BYTE_ARRAY, ','); DataRow dataRow = factory.create(1); dataRow.set(lnfAttribute, dmValue); exampleTable.addDataRow(dataRow); output = exampleTable.createExampleSet(); // some statistics //ProcessStatistics.getInstance().addFingerprintStringLength(fingerprintBuffer.length()); } } catch (Exception e) { System.out.println("Exception in FingerprintCreation " + e.toString()); } return new IOObject[] {output}; } private double interpolate(double x1, double x2, double y1, double y2, double q11, double q21, double q12, double q22, double x, double y) { double result = 0.0; result += q11 * (x2-x) * (y2-y); result += q21 * (x-x1) * (y2-y); result += q12 * (x2-x) * (y-y1); result += q22 * (x-x1) * (y-y1); return result; } /** * @param mapArray array with pixel values * @param i current x position * @param j current y position * @param r radius of circle * @param p number of points * @return */ private double[] getCircle(MapValue mv, int i, int j, double R, double P) { double[] result = new double[(int)P]; for (double p=1; p<=P; p++) { double x = -R * Math.sin(2.0*Math.PI*p/P); double y = R * Math.cos(2.0*Math.PI*p/P); if ((int)(x*10000.0) == 0) x=0; if ((int)(y*10000.0) == 0) y=0; double x1 = Math.floor(x); double x2 = Math.ceil(x); double y1 = Math.floor(y); double y2 = Math.ceil(y); // hack for -0 if (x1==-0) x1=0; if (x2==-0) x2=0; if (y1==-0) y1=0; if (y2==-0) y2=0; if ((x1 == x2) && (y1 == y2)) result[(int)p-1] = mv.getValueAtId(i+(int)x,j+(int)y); else { result[(int)p-1] = interpolate(x1,x2,y1,y2,mv.getValueAtId((int)(i+x1),(int)(j+y1)), mv.getValueAtId((int)(i+x2),(int)(j+y1)), mv.getValueAtId((int)(i+x1),(int)(j+y2)), mv.getValueAtId((int)(i+x2),(int)(j+y2)), x,y); } } return result; } @Override public List<ParameterType> getParameterTypes() { List<ParameterType> types = super.getParameterTypes(); types.add(new ParameterTypeString(PARAMETER_MAP_NAME, "", "map")); types.add(new ParameterTypeCategory("rotation", "", new String[]{"no", "yes"}, 0)); types.add(new ParameterTypeInt("radius", "", 1, Integer.MAX_VALUE, 1)); types.add(new ParameterTypeInt("points", "", 4, Integer.MAX_VALUE, 8)); types.add(new ParameterTypeBoolean("normalize", "", false)); return types; } @Override public Class<?>[] getInputClasses() { return new Class[] {ComplexExampleSet.class}; } @Override public Class<?>[] getOutputClasses() { return new Class[] {ExampleSet.class}; } @Override public Capability[] getInputCapabilities() { Capability[] list = new Capability[]{ CapabilityBuilder.buildCapability(new int[]{Ontology.MAP}, true)}; return list; } @Override public Capability[] getOutputCapabilities() { Capability[] list = new Capability[]{ CapabilityBuilder.buildCapability(new int[]{Ontology.DATA_MAP}, true)}; return list; } }