Inference engine generated annotations again for the EyeTracking, but it has location type errors.
// written to but not overwritten by the higher value
private Hashtable<FlatMethod, SharedLocMap> mapFlatMethodToDeleteSet;
+ private Hashtable<FlatMethod, SharedLocMap> mapFlatMethodToMustClearMap;
+
// maps a flat method to the S SET that is a set of heap path to shared
// locations that are overwritten by the higher value
private Hashtable<FlatMethod, SharedLocMap> mapFlatMethodToSharedLocMap;
private Hashtable<FlatNode, SharedLocMap> mapFlatNodeToSharedLocMapping;
private Hashtable<FlatNode, SharedLocMap> mapFlatNodeToDeleteSet;
+ private Hashtable<FlatNode, SharedLocMap> mapFlatNodeToMustClearMap;
private LoopFinder ssjavaLoop;
private Set<FlatNode> loopIncElements;
private Set<NTuple<Descriptor>> calleeUnionBoundMayWriteSet;
private SharedLocMap calleeUnionBoundDeleteSet;
private SharedLocMap calleeIntersectBoundSharedSet;
+ private SharedLocMap calleeIntersectBoundMustClearSet;
Set<TempDescriptor> liveInTempSetToEventLoop;
this.mapFlatNodeToDeleteSet = new Hashtable<FlatNode, SharedLocMap>();
this.liveness = new Liveness();
this.liveInTempSetToEventLoop = new HashSet<TempDescriptor>();
+ this.mapFlatNodeToMustClearMap = new Hashtable<FlatNode, SharedLocMap>();
+ this.calleeIntersectBoundMustClearSet = new SharedLocMap();
+ this.mapFlatMethodToMustClearMap = new Hashtable<FlatMethod, SharedLocMap>();
}
public void definitelyWrittenCheck() {
SharedLocMap sharedLocMap = new SharedLocMap();
SharedLocMap deleteSet = new SharedLocMap();
+ SharedLocMap mustClearMap = new SharedLocMap();
- sharedLoc_analyzeMethod(fm, sharedLocMap, deleteSet);
+ sharedLoc_analyzeMethod(fm, sharedLocMap, deleteSet, mustClearMap);
SharedLocMap prevSharedLocMap = mapFlatMethodToSharedLocMap.get(fm);
SharedLocMap prevDeleteSet = mapFlatMethodToDeleteSet.get(fm);
+ SharedLocMap prevMustClearMap = mapFlatMethodToMustClearMap.get(fm);
- if (!(deleteSet.equals(prevDeleteSet) && sharedLocMap.equals(prevSharedLocMap))) {
+ if (!(deleteSet.equals(prevDeleteSet) && sharedLocMap.equals(prevSharedLocMap) && mustClearMap
+ .equals(prevMustClearMap))) {
mapFlatMethodToSharedLocMap.put(fm, sharedLocMap);
mapFlatMethodToDeleteSet.put(fm, deleteSet);
+ mapFlatMethodToMustClearMap.put(fm, mustClearMap);
// results for callee changed, so enqueue dependents caller for
// further
}
SharedLocMap sharedLocMap = new SharedLocMap();
SharedLocMap deleteSet = new SharedLocMap();
+ SharedLocMap mustClearMap = new SharedLocMap();
sharedLoc_analyzeBody(state.getMethodFlat(methodContainingSSJavaLoop),
- ssjava.getSSJavaLoopEntrance(), sharedLocMap, deleteSet, true);
+ ssjava.getSSJavaLoopEntrance(), sharedLocMap, deleteSet, mustClearMap, true);
}
private void sharedLoc_analyzeMethod(FlatMethod fm, SharedLocMap sharedLocMap,
- SharedLocMap deleteSet) {
+ SharedLocMap deleteSet, SharedLocMap mustClearMap) {
if (state.SSJAVADEBUG) {
System.out.println("SSJAVA: Definite clearance for shared locations Analyzing: " + fm);
}
- sharedLoc_analyzeBody(fm, fm, sharedLocMap, deleteSet, false);
+ sharedLoc_analyzeBody(fm, fm, sharedLocMap, deleteSet, mustClearMap, false);
}
private void sharedLoc_analyzeBody(FlatMethod fm, FlatNode startNode, SharedLocMap sharedLocMap,
- SharedLocMap deleteSet, boolean isEventLoopBody) {
+ SharedLocMap deleteSet, SharedLocMap mustClearMap, boolean isEventLoopBody) {
// intraprocedural analysis
Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
SharedLocMap currSharedSet = new SharedLocMap();
SharedLocMap currDeleteSet = new SharedLocMap();
+ SharedLocMap currMustClearMap = new SharedLocMap();
for (int i = 0; i < fn.numPrev(); i++) {
FlatNode prevFn = fn.getPrev(i);
if (inDeleteLoc != null) {
mergeDeleteSet(currDeleteSet, inDeleteLoc);
}
+
+ SharedLocMap inMustClearMap = mapFlatNodeToMustClearMap.get(prevFn);
+ if (inMustClearMap != null) {
+ mergeSharedLocMap(currMustClearMap, inMustClearMap);
+ }
+
}
- sharedLoc_nodeActions(fm, fn, currSharedSet, currDeleteSet, sharedLocMap, deleteSet,
- isEventLoopBody);
+ sharedLoc_nodeActions(fm, fn, currSharedSet, currDeleteSet, currMustClearMap, sharedLocMap,
+ deleteSet, mustClearMap, isEventLoopBody);
SharedLocMap prevSharedSet = mapFlatNodeToSharedLocMapping.get(fn);
SharedLocMap prevDeleteSet = mapFlatNodeToDeleteSet.get(fn);
+ SharedLocMap prevMustClearMap = mapFlatNodeToMustClearMap.get(fn);
- if (!(currSharedSet.equals(prevSharedSet) && currDeleteSet.equals(prevDeleteSet))) {
+ if (!(currSharedSet.equals(prevSharedSet) && currDeleteSet.equals(prevDeleteSet) && currMustClearMap
+ .equals(prevMustClearMap))) {
mapFlatNodeToSharedLocMapping.put(fn, currSharedSet);
mapFlatNodeToDeleteSet.put(fn, currDeleteSet);
+ mapFlatNodeToMustClearMap.put(fn, currMustClearMap);
for (int i = 0; i < fn.numNext(); i++) {
FlatNode nn = fn.getNext(i);
if ((!isEventLoopBody) || loopIncElements.contains(nn)) {
}
private void sharedLoc_nodeActions(FlatMethod fm, FlatNode fn, SharedLocMap curr,
- SharedLocMap currDeleteSet, SharedLocMap sharedLocMap, SharedLocMap deleteSet,
- boolean isEventLoopBody) {
+ SharedLocMap currDeleteSet, SharedLocMap currMustClearMap, SharedLocMap sharedLocMap,
+ SharedLocMap deleteSet, SharedLocMap mustClearMap, boolean isEventLoopBody) {
MethodDescriptor md = fm.getMethod();
TempDescriptor rhs;
FieldDescriptor fld;
+ NTuple<Location> fieldLocTuple = null;
+ Location fieldLoc = null;
+ boolean isHigherWriteCase = false;
+
switch (fn.kind()) {
case FKind.FlatOpNode: {
case FKind.FlatSetFieldNode:
case FKind.FlatSetElementNode: {
- Location fieldLoc;
if (fn.kind() == FKind.FlatSetFieldNode) {
FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
lhs = fsfn.getDst();
break;
}
- NTuple<Location> fieldLocTuple = new NTuple<Location>();
+ fieldLocTuple = new NTuple<Location>();
if (fld.isStatic()) {
if (fld.isFinal()) {
// in this case, fld has TOP location
if (!ssjava.isSameHeightWrite(fn)) {
computeGENSetForHigherWrite(curr, genSet, fieldLocTuple, fldHeapPath);
updateDeleteSetForHigherWrite(currDeleteSet, fieldLocTuple, fldHeapPath);
+
+ isHigherWriteCase = true;
+
} else {
computeGENSetForSameHeightWrite(curr, genSet, fieldLocTuple, fldHeapPath);
updateDeleteSetForSameHeightWrite(currDeleteSet, fieldLocTuple, fldHeapPath);
generateKILLSetForFlatCall(curr, killSet);
generateGENSetForFlatCall(curr, genSet);
+ Set<NTuple<Location>> locTupleSet = calleeIntersectBoundMustClearSet.keySet();
+ for (Iterator iterator = locTupleSet.iterator(); iterator.hasNext();) {
+ NTuple<Location> locTupleKey = (NTuple<Location>) iterator.next();
+ currMustClearMap.addWrite(locTupleKey, calleeIntersectBoundMustClearSet.get(locTupleKey));
+ }
+
}
break;
// merge the current delete/shared loc mapping
mergeSharedLocMap(sharedLocMap, curr);
mergeDeleteSet(deleteSet, currDeleteSet);
-
+ mergeSharedLocMap(mustClearMap, currMustClearMap);
}
break;
}
computeNewMapping(curr, killSet, genSet);
+ if (isHigherWriteCase) {
+ // check all locations with the same shared location are cleared out at this point
+ Set<NTuple<Descriptor>> writtenSet = curr.get(fieldLocTuple);
+ Set<Descriptor> requirementSet = ssjava.getSharedDescSet(fieldLoc);
+
+ if (checkAllSharedLocationsAreOverwritten(requirementSet, writtenSet)) {
+ currMustClearMap.addWrite(fieldLocTuple, writtenSet);
+ }
+ }
+ }
+
+ private boolean checkAllSharedLocationsAreOverwritten(Set<Descriptor> sharedDescSet,
+ Set<NTuple<Descriptor>> writtenSet) {
+
+ if (sharedDescSet == null || writtenSet == null) {
+ return false;
+ }
+ Set<Descriptor> writtenDescSet = new HashSet<Descriptor>();
+ for (Iterator iterator = writtenSet.iterator(); iterator.hasNext();) {
+ NTuple<Descriptor> tuple = (NTuple<Descriptor>) iterator.next();
+ writtenDescSet.add(tuple.get(tuple.size() - 1));
+ }
+
+ return writtenDescSet.containsAll(sharedDescSet);
+ // return sharedDescSet.containsAll(writtenDescSet);
}
if (currWriteSet != null) {
genSet.addWrite(locTuple, currWriteSet);
}
-
genSet.addWrite(locTuple, hp);
}
private void computeSharedCoverSet_analyzeMethod(FlatMethod fm, boolean onlyVisitSSJavaLoop) {
- // System.out.println("computeSharedCoverSet_analyzeMethod=" + fm);
MethodDescriptor md = fm.getMethod();
Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
Set<NTuple<Descriptor>> writtenSet =
mapFlatNodeToSharedLocMapping.get(fn).get(varLocTuple);
- if (isCovered(varLocTuple, writtenSet)) {
+ Set<NTuple<Descriptor>> mustClearSet =
+ mapFlatNodeToMustClearMap.get(fn).get(varLocTuple);
+
+ if (isCovered(varLocTuple, writtenSet, mustClearSet)) {
computeKILLSetForSharedWrite(curr, writtenSet, readWriteKillSet);
computeGENSetForSharedAllCoverWrite(curr, writtenSet, readWriteGenSet);
} else {
Set<NTuple<Descriptor>> writtenSet =
mapFlatNodeToSharedLocMapping.get(fn).get(fieldLocTuple);
-
if (isCovered(fieldLocTuple, writtenSet)) {
computeKILLSetForSharedWrite(curr, writtenSet, readWriteKillSet);
computeGENSetForSharedAllCoverWrite(curr, writtenSet, readWriteGenSet);
case FKind.FlatCall: {
FlatCall fc = (FlatCall) fn;
-
SharedLocMap sharedLocMap = mapFlatNodeToSharedLocMapping.get(fc);
- generateKILLSetForFlatCall(fc, curr, sharedLocMap, readWriteKillSet);
- generateGENSetForFlatCall(fc, sharedLocMap, readWriteGenSet);
+ SharedLocMap mustClearMap = mapFlatNodeToMustClearMap.get(fc);
+ generateKILLSetForFlatCall(fc, curr, sharedLocMap, mustClearMap, readWriteKillSet);
+ generateGENSetForFlatCall(fc, sharedLocMap, mustClearMap, readWriteGenSet);
}
break;
}
- private boolean isCovered(NTuple<Location> locTuple, Set<NTuple<Descriptor>> inSet) {
+ private boolean isCovered(NTuple<Location> locTuple, Set<NTuple<Descriptor>> curWrittenSet) {
- if (inSet == null) {
+ Set<NTuple<Descriptor>> coverSet =
+ mapMethodToSharedLocCoverSet.get(methodContainingSSJavaLoop).get(locTuple);
+
+ if (curWrittenSet == null) {
return false;
}
+ return curWrittenSet.containsAll(coverSet);
+ }
+
+ private boolean isCovered(NTuple<Location> locTuple, Set<NTuple<Descriptor>> curWrittenSet,
+ Set<NTuple<Descriptor>> mustClearSet) {
+
Set<NTuple<Descriptor>> coverSet =
mapMethodToSharedLocCoverSet.get(methodContainingSSJavaLoop).get(locTuple);
- return inSet.containsAll(coverSet);
+ if (mustClearSet != null && mustClearSet.containsAll(coverSet)) {
+ return true;
+ }
+
+ if (curWrittenSet == null) {
+ return false;
+ }
+
+ return curWrittenSet.containsAll(coverSet);
}
private void checkManyRead(FlatCall fc, Hashtable<NTuple<Descriptor>, Set<WriteAge>> curr) {
-
Set<NTuple<Descriptor>> boundReadSet = mapFlatNodeToBoundReadSet.get(fc);
-
for (Iterator iterator = boundReadSet.iterator(); iterator.hasNext();) {
NTuple<Descriptor> readHeapPath = (NTuple<Descriptor>) iterator.next();
Set<WriteAge> writeAgeSet = curr.get(readHeapPath);
}
private void generateGENSetForFlatCall(FlatCall fc, SharedLocMap sharedLocMap,
- Hashtable<NTuple<Descriptor>, Set<WriteAge>> GENSet) {
+ SharedLocMap mustClearMap, Hashtable<NTuple<Descriptor>, Set<WriteAge>> GENSet) {
Set<NTuple<Descriptor>> boundMayWriteSet = mapFlatNodeToBoundMayWriteSet.get(fc);
Set<NTuple<Descriptor>> sharedWriteHeapPathSet = sharedLocMap.get(locTuple);
- if (isCovered(locTuple, sharedLocMap.get(locTuple))) {
+ if (isCovered(locTuple, sharedLocMap.get(locTuple), mustClearMap.get(locTuple))) {
// if it is covered, add all of heap paths belong to the same shared
// loc with write age 0
-
for (Iterator iterator2 = sharedWriteHeapPathSet.iterator(); iterator2.hasNext();) {
NTuple<Descriptor> sharedHeapPath = (NTuple<Descriptor>) iterator2.next();
addWriteAgeToSet(sharedHeapPath, GENSet, new WriteAge(0));
private void generateKILLSetForFlatCall(FlatCall fc,
Hashtable<NTuple<Descriptor>, Set<WriteAge>> curr, SharedLocMap sharedLocMap,
- Hashtable<NTuple<Descriptor>, Set<WriteAge>> KILLSet) {
+ SharedLocMap mustClearMap, Hashtable<NTuple<Descriptor>, Set<WriteAge>> KILLSet) {
Set<NTuple<Descriptor>> boundMustWriteSet = mapFlatNodeToBoundMustWriteSet.get(fc);
if (isSharedLocation(heapPath)) {
NTuple<Location> locTuple = getLocationTuple(heapPath);
- if (isCovered(locTuple, sharedLocMap.get(locTuple)) && curr.containsKey(heapPath)) {
+ if (isCovered(locTuple, sharedLocMap.get(locTuple), mustClearMap.get(locTuple))
+ && curr.containsKey(heapPath)) {
// if it is shared loc and corresponding shared loc has been covered
KILLSet.put(heapPath, curr.get(heapPath));
}
NTuple<Location> calleeLocationPath = deriveLocationTuple(mdCallee, calleeParam);
SharedLocMap calleeDeleteSet = mapFlatMethodToDeleteSet.get(calleeFlatMethod);
SharedLocMap calleeSharedLocMap = mapFlatMethodToSharedLocMap.get(calleeFlatMethod);
+ SharedLocMap calleeMustClearMap = mapFlatMethodToMustClearMap.get(calleeFlatMethod);
if (calleeDeleteSet != null) {
createNewMappingOfDeleteSet(callerArgLocationPath, callerArgHeapPath,
calleeLocationPath, calleeSharedLocMap);
}
+ if (calleeMustClearMap != null) {
+ createNewMappingOfMustClearMap(callerArgLocationPath, callerArgHeapPath,
+ calleeLocationPath, calleeMustClearMap);
+ }
+
}
}
}
+ private void createNewMappingOfMustClearMap(NTuple<Location> callerArgLocationPath,
+ NTuple<Descriptor> callerArgHeapPath, NTuple<Location> calleeLocationPath,
+ SharedLocMap calleeMustClearMap) {
+
+ SharedLocMap calleeParamSharedSet =
+ calleeMustClearMap.getHeapPathStartedWith(calleeLocationPath);
+
+ Set<NTuple<Location>> keySet = calleeParamSharedSet.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ NTuple<Location> calleeLocTupleKey = (NTuple<Location>) iterator.next();
+ Set<NTuple<Descriptor>> heapPathSet = calleeParamSharedSet.get(calleeLocTupleKey);
+ Set<NTuple<Descriptor>> boundHeapPathSet = new HashSet<NTuple<Descriptor>>();
+ for (Iterator iterator2 = heapPathSet.iterator(); iterator2.hasNext();) {
+ NTuple<Descriptor> calleeHeapPath = (NTuple<Descriptor>) iterator2.next();
+ boundHeapPathSet.add(bindHeapPath(callerArgHeapPath, calleeHeapPath));
+ }
+ calleeIntersectBoundMustClearSet.intersect(
+ bindLocationPath(callerArgLocationPath, calleeLocTupleKey), boundHeapPathSet);
+ }
+
+ }
+
private void createNewMappingOfDeleteSet(NTuple<Location> callerArgLocationPath,
NTuple<Descriptor> callerArgHeapPath, NTuple<Location> calleeLocationPath,
SharedLocMap calleeDeleteSet) {
// System.out.println("base location=" + callerBaseLoc + " constraint=" +
// constraint);
- for (int i = 0; i < calleeParamList.size(); i++) {
+ System.out.println("calleeParamList=" + calleeParamList);
+ int offset = 0;
+ if (!md.isStatic()) {
+ offset = 1;
+ }
+ for (int i = offset; i < calleeParamList.size(); i++) {
CompositeLocation calleeParamLoc = calleeParamList.get(i);
if (calleeParamLoc.get(0).equals(calleeThisLoc) && calleeParamLoc.getSize() > 1) {
continue;
}
+ System.out.println("---idx=" + i + " callerArgLoc=" + callerArgLoc + " paramLocation="
+ + paramLocation);
// if (!CompositeLattice.isGreaterThan(callerArgLoc, paramLocation, errorMsg)) {
if (CompositeLattice.compare(callerArgLoc, paramLocation, true, errorMsg) == ComparisonResult.LESS) {
throw new Error("Caller argument '" + min.getArg(i).printNode(0) + " : " + callerArgLoc
Set<FlatNode> flatNodeSet = ssjava.getBuildFlat().getFlatNodeSet(an);
for (Iterator iterator = flatNodeSet.iterator(); iterator.hasNext();) {
FlatNode fn = (FlatNode) iterator.next();
+ System.out.println("SAMEHEIGHT!");
ssjava.addSameHeightWriteFlatNode(fn);
}
+ } else {
+ System.out.println("NOT SAME HEIGHT!");
}
} else {
addLocationType(fd.getType(), loc);
+ if (ssjava.isSharedLocation(loc)) {
+ ssjava.addSharedDesc(loc, fd);
+ }
}
}
FlowReturnNode rnode = (FlowReturnNode) originalSrcNode;
Set<NTuple<Descriptor>> rtupleSetFromRNode = rnode.getReturnTupleSet();
Set<NTuple<Descriptor>> rtupleSet = getReturnTupleSet(rtupleSetFromRNode);
- System.out.println("#rnode=" + rnode + " rtupleSet=" + rtupleSet);
+ // System.out.println("#rnode=" + rnode + " rtupleSet=" + rtupleSet);
for (Iterator iterator2 = rtupleSet.iterator(); iterator2.hasNext();) {
NTuple<Descriptor> rtuple = (NTuple<Descriptor>) iterator2.next();
if (rtuple.startsWith(prefix)) {
private boolean isSkeleton;
+ private boolean isFormHolder = false;
+
public boolean isIntermediate() {
return isIntermediate;
}
this.isIntermediate = isIntermediate;
}
+ public void setFormHolder(boolean in) {
+ isFormHolder = in;
+ }
+
+ public boolean isFromHolder() {
+ return isFormHolder;
+ }
+
public Set<FlowNode> getFieldNodeSet() {
return fieldNodeSet;
}
System.out.println("\nSSJAVA: Add addtional ordering constriants:");
MethodDescriptor methodEventLoopDesc = ssjava.getMethodContainingSSJavaLoop();
addAddtionalOrderingConstraints(methodEventLoopDesc);
+ // calculateReturnHolderLocation();
+ }
+
+ private void calculateReturnHolderLocation() {
+ LinkedList<MethodDescriptor> methodDescList =
+ (LinkedList<MethodDescriptor>) toanalyze_methodDescList.clone();
+
+ while (!methodDescList.isEmpty()) {
+ MethodDescriptor md = methodDescList.removeLast();
+
+ FlowGraph fg = getFlowGraph(md);
+ Set<FlowNode> nodeSet = fg.getNodeSet();
+ for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
+ FlowNode flowNode = (FlowNode) iterator.next();
+ if (flowNode.isFromHolder()) {
+ calculateCompositeLocationFromFlowGraph(md, flowNode);
+ }
+ }
+
+ }
}
private void updateCompositeLocationAssignments() {
}
+ private CompositeLocation calculateCompositeLocationFromFlowGraph(MethodDescriptor md,
+ FlowNode node) {
+
+ System.out.println("#############################################################");
+ System.out.println("calculateCompositeLocationFromFlowGraph=" + node);
+
+ FlowGraph flowGraph = getFlowGraph(md);
+ // NTuple<Location> paramLocTuple = translateToLocTuple(md, paramNode.getDescTuple());
+ // GlobalFlowNode paramGlobalNode = subGlobalFlowGraph.getFlowNode(paramLocTuple);
+
+ List<NTuple<Location>> prefixList = calculatePrefixListFlowGraph(flowGraph, node);
+
+ // Set<GlobalFlowNode> reachableNodeSet =
+ // subGlobalFlowGraph.getReachableNodeSetByPrefix(paramGlobalNode.getLocTuple().get(0));
+ //
+ Set<FlowNode> reachableNodeSet =
+ flowGraph.getReachableSetFrom(node.getDescTuple().subList(0, 1));
+
+ // Set<GlobalFlowNode> reachNodeSet = globalFlowGraph.getReachableNodeSetFrom(node);
+
+ // System.out.println("node=" + node + " prefixList=" + prefixList);
+
+ for (int i = 0; i < prefixList.size(); i++) {
+ NTuple<Location> curPrefix = prefixList.get(i);
+ Set<NTuple<Location>> reachableCommonPrefixSet = new HashSet<NTuple<Location>>();
+
+ for (Iterator iterator2 = reachableNodeSet.iterator(); iterator2.hasNext();) {
+ FlowNode reachNode = (FlowNode) iterator2.next();
+ NTuple<Location> reachLocTuple = translateToLocTuple(md, reachNode.getCurrentDescTuple());
+ if (reachLocTuple.startsWith(curPrefix)) {
+ reachableCommonPrefixSet.add(reachLocTuple);
+ }
+ }
+ // System.out.println("reachableCommonPrefixSet=" + reachableCommonPrefixSet);
+
+ if (!reachableCommonPrefixSet.isEmpty()) {
+
+ MethodDescriptor curPrefixFirstElementMethodDesc =
+ (MethodDescriptor) curPrefix.get(0).getDescriptor();
+
+ // MethodDescriptor nodePrefixLocFirstElementMethodDesc =
+ // (MethodDescriptor) prefixLoc.getDescriptor();
+
+ // System.out.println("curPrefixFirstElementMethodDesc=" +
+ // curPrefixFirstElementMethodDesc);
+ // System.out.println("nodePrefixLocFirstElementMethodDesc="
+ // + nodePrefixLocFirstElementMethodDesc);
+
+ // TODO
+ // if (!node.getLocTuple().startsWith(curPrefix.get(0))) {
+
+ Location curPrefixLocalLoc = curPrefix.get(0);
+
+ Location targetLocalLoc = new Location(md, node.getDescTuple().get(0));
+ // Location targetLocalLoc = paramGlobalNode.getLocTuple().get(0);
+
+ CompositeLocation newCompLoc = generateCompositeLocation(curPrefix);
+ System.out.println("NEED2ASSIGN COMP LOC TO " + node + " with prefix=" + curPrefix);
+ System.out.println("-targetLocalLoc=" + targetLocalLoc + " - newCompLoc=" + newCompLoc);
+
+ // // makes sure that a newly generated location appears in the hierarchy graph
+ // for (int compIdx = 0; compIdx < newCompLoc.getSize(); compIdx++) {
+ // Location curLoc = newCompLoc.get(compIdx);
+ // getHierarchyGraph(curLoc.getDescriptor()).getHNode(curLoc.getLocDescriptor());
+ // }
+ // subGlobalFlowGraph.addMapLocationToInferCompositeLocation(targetLocalLoc, newCompLoc);
+ node.setCompositeLocation(newCompLoc);
+
+ return newCompLoc;
+
+ }
+
+ }
+ return null;
+ }
+
+ private List<NTuple<Location>> calculatePrefixListFlowGraph(FlowGraph graph, FlowNode node) {
+
+ System.out.println("\n##### calculatePrefixList node=" + node);
+
+ MethodDescriptor md = graph.getMethodDescriptor();
+ Set<FlowNode> incomingNodeSetPrefix =
+ graph.getIncomingNodeSetByPrefix(node.getDescTuple().get(0));
+ // System.out.println("---incomingNodeSetPrefix=" + incomingNodeSetPrefix);
+
+ Set<FlowNode> reachableNodeSetPrefix =
+ graph.getReachableSetFrom(node.getDescTuple().subList(0, 1));
+ // System.out.println("---reachableNodeSetPrefix=" + reachableNodeSetPrefix);
+
+ List<NTuple<Location>> prefixList = new ArrayList<NTuple<Location>>();
+
+ for (Iterator iterator = incomingNodeSetPrefix.iterator(); iterator.hasNext();) {
+ FlowNode inNode = (FlowNode) iterator.next();
+ NTuple<Location> inNodeTuple = translateToLocTuple(md, inNode.getCurrentDescTuple());
+
+ // if (inNodeTuple.get(0).getLocDescriptor() instanceof InterDescriptor
+ // || inNodeTuple.get(0).getLocDescriptor().equals(GLOBALDESC)) {
+ // continue;
+ // }
+
+ for (int i = 1; i < inNodeTuple.size(); i++) {
+ NTuple<Location> prefix = inNodeTuple.subList(0, i);
+ if (!prefixList.contains(prefix)) {
+ prefixList.add(prefix);
+ }
+ }
+ }
+
+ Collections.sort(prefixList, new Comparator<NTuple<Location>>() {
+ public int compare(NTuple<Location> arg0, NTuple<Location> arg1) {
+ int s0 = arg0.size();
+ int s1 = arg1.size();
+ if (s0 > s1) {
+ return -1;
+ } else if (s0 == s1) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ });
+
+ return prefixList;
+
+ }
+
private boolean containsClassDesc(ClassDescriptor cd, NTuple<Location> prefixLocTuple) {
for (int i = 0; i < prefixLocTuple.size(); i++) {
Location loc = prefixLocTuple.get(i);
NTuple<Location> locTuple = new NTuple<Location>();
Descriptor enclosingDesc = md;
- System.out.println("md=" + md + " descTuple=" + descTuple);
for (int i = 0; i < descTuple.size(); i++) {
Descriptor desc = descTuple.get(i);
if (mdCallee.getReturnType() != null && !mdCallee.getReturnType().isVoid()) {
FlowReturnNode setNode = getFlowGraph(mdCaller).createReturnNode(min);
- System.out.println("ADD TUPLESET=" + tupleSet + " to returnnode=" + setNode);
if (needToGenerateInterLoc(tupleSet)) {
System.out.println("20");
FlowGraph fg = getFlowGraph(mdCaller);
- NTuple<Descriptor> interTuple = fg.createIntermediateNode().getDescTuple();
+ FlowNode interNode = fg.createIntermediateNode();
+ interNode.setFormHolder(true);
+
+ NTuple<Descriptor> interTuple = interNode.getDescTuple();
for (Iterator iterator = tupleSet.iterator(); iterator.hasNext();) {
NTuple<Descriptor> tuple = (NTuple<Descriptor>) iterator.next();
}
setNode.addTuple(interTuple);
+ System.out.println("ADD TUPLESET=" + interTuple + " to returnnode=" + setNode);
+
} else {
setNode.addTupleSet(tupleSet);
- }
+ System.out.println("ADD TUPLESET=" + tupleSet + " to returnnode=" + setNode);
+ }
+ // setNode.addTupleSet(tupleSet);
nodeSet.addTuple(setNode.getDescTuple());
}
// keep the field ownership from the linear type checking
Hashtable<MethodDescriptor, Set<FieldDescriptor>> mapMethodToOwnedFieldSet;
-
+
Set<FlatNode> sameHeightWriteFlatNodeSet;
CallGraph callgraph;
private LinkedList<MethodDescriptor> sortedDescriptors;
+ private Map<Location, Set<Descriptor>> mapSharedLocToDescSet;
+
public SSJavaAnalysis(State state, TypeUtil tu, BuildFlat bf, CallGraph callgraph) {
this.state = state;
this.tu = tu;
this.mapDescriptorToSetDependents = new Hashtable<Descriptor, Set<MethodDescriptor>>();
this.sortedDescriptors = new LinkedList<MethodDescriptor>();
this.md2pcLoc = new HashMap<MethodDescriptor, CompositeLocation>();
+ this.mapSharedLocToDescSet = new HashMap<Location, Set<Descriptor>>();
}
public void doCheck() {
return (LinkedList<MethodDescriptor>) sortedDescriptors.clone();
}
+ public void addSharedDesc(Location loc, Descriptor fd) {
+ if (!mapSharedLocToDescSet.containsKey(loc)) {
+ mapSharedLocToDescSet.put(loc, new HashSet<Descriptor>());
+ }
+ mapSharedLocToDescSet.get(loc).add(fd);
+ }
+
+ public Set<Descriptor> getSharedDescSet(Location loc) {
+ return mapSharedLocToDescSet.get(loc);
+ }
+
private void inference() {
LocationInference inferEngine = new LocationInference(this, state);
inferEngine.inference();
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
- *
+ * private Point readEyes(@LOC("IN") Image image, @LOC("IN") Rectangle2D rect) {
+ @LOC("OUT") EyeDetector ed = new EyeDetector(image, rect);
+ return ed.detectEye();
+ }
* You should have received a copy of the GNU Lesser General Public License
* along with LEA. If not, see <http://www.gnu.org/licenses/>.
*/
*
* @author Florian
*/
-@LATTICE("CS<C,C*")
+@LATTICE("C<CS,CS<CUR,CUR<PREV,PREV<SIZE,PREV*,C*,CUR*")
@METHODDEFAULT("OUT<THIS,THIS<IN,THISLOC=THIS,RETURNLOC=OUT")
public class ClassifierTree {
@LOC("CS")
private Classifier classifiers[];
- public ClassifierTree(int size) {
+ @LOC("CUR")
+ double x;
+ @LOC("CUR")
+ double y;
+ @LOC("CUR")
+ double width;
+ @LOC("CUR")
+ double height;
+
+ @LOC("SIZE")
+ int size;
+
+ @LATTICE("THIS<IN,THISLOC=THIS")
+ public ClassifierTree(@LOC("IN") int size) {
+ this.size = size;
classifiers = new Classifier[size];
+ x = -1;
+ y = -1;
+ width = -1;
+ height = -1;
}
public void addClassifier(@LOC("IN") int idx, @LOC("IN") Classifier c) {
}
/**
- * Locates a face by searching radial starting at the last known position. If
- * lastCoordinates are null we simply start in the center of the image.
+ * Locates a face by searching radial starting at the last known position. If lastCoordinates are
+ * null we simply start in the center of the image.
* <p>
- * TODO: This method could quite possible be tweaked so that face recognition
- * would be much faster
+ * TODO: This method could quite possible be tweaked so that face recognition would be much faster
*
* @param image
* the image to process
* @param lastCoordinates
* the last known coordinates or null if unknown
- * @return an rectangle representing the actual face position on success or
- * null if no face could be detected
+ * @return an rectangle representing the actual face position on success or null if no face could
+ * be detected
*/
@LATTICE("OUT<CXY,CXY<THIS,THIS<V,V<IMG,IMG<C,C<IN,C*,V*,FACTOR*,CXY*,THISLOC=THIS,RETURNLOC=OUT,GLOBALLOC=IN")
- @PCLOC("C")
- public Rectangle2D locateFaceRadial(@LOC("IN") Image smallImage,
- @LOC("THIS,ClassifierTree.C") Rectangle2D lastCoordinates) {
+ public void locateFaceRadial(@LOC("IN") Image smallImage) {
+
+ @LOC("THIS,ClassifierTree.CUR") double px = x;
+ @LOC("THIS,ClassifierTree.CUR") double py = y;
+ @LOC("THIS,ClassifierTree.CUR") double pwidth = width;
+ @LOC("THIS,ClassifierTree.CUR") double pheight = height;
+
+ x = -1;
+ y = -1;
+ width = -1;
+ height = -1;
@LOC("IMG") IntegralImageData imageData = new IntegralImageData(smallImage);
@LOC("IN") float originalImageFactor = 1;
-
- if (lastCoordinates == null) {
+ if (px == -1) {
+ // if(true){
// if we don't have a last coordinate we just begin in the center
- @LOC("THIS,ClassifierTree.C") int smallImageMaxDimension =
+ @LOC("THIS,ClassifierTree.PREV") int smallImageMaxDimension =
Math.min(smallImage.getWidth(), smallImage.getHeight());
- lastCoordinates =
- new Rectangle2D((smallImage.getWidth() - smallImageMaxDimension) / 2.0,
- (smallImage.getHeight() - smallImageMaxDimension) / 2.0, smallImageMaxDimension,
- smallImageMaxDimension);
- // System.out.println("lastCoordinates=" + lastCoordinates);
+
+ px = (smallImage.getWidth() - smallImageMaxDimension) / 2.0;
+ py = (smallImage.getHeight() - smallImageMaxDimension) / 2.0;
+ pwidth = smallImageMaxDimension;
+ pheight = smallImageMaxDimension;
} else {
// first we have to scale the last coodinates back relative to the resized
// image
- lastCoordinates =
- new Rectangle2D((lastCoordinates.getX() * (1 / originalImageFactor)),
- (lastCoordinates.getY() * (1 / originalImageFactor)),
- (lastCoordinates.getWidth() * (1 / originalImageFactor)),
- (lastCoordinates.getHeight() * (1 / originalImageFactor)));
+ px = px * (1 / originalImageFactor);
+ py = py * (1 / originalImageFactor);
+ pwidth = pwidth * (1 / originalImageFactor);
+ pheight = pheight * (1 / originalImageFactor);
}
- @LOC("THIS,ClassifierTree.C") float startFactor = (float) (lastCoordinates.getWidth() / 100.0f);
+
+ @LOC("THIS,ClassifierTree.CUR") float startFactor = (float) (pwidth / 100.0f);
// first we calculate the maximum scale factor for our 200x200 image
- @LOC("THIS,ClassifierTree.C") float maxScaleFactor =
+ @LOC("THIS,ClassifierTree.CUR") float maxScaleFactor =
Math.min(imageData.getWidth() / 100f, imageData.getHeight() / 100f);
// maxScaleFactor = 1.0f;
// we simply won't recognize faces that are smaller than 40x40 px
- @LOC("THIS,ClassifierTree.C") float minScaleFactor = 0.5f;
+ @LOC("THIS,ClassifierTree.CUR") float minScaleFactor = 0.5f;
- @LOC("THIS,ClassifierTree.C") float maxScaleDifference =
+ @LOC("THIS,ClassifierTree.CUR") float maxScaleDifference =
Math.max(Math.abs(maxScaleFactor - startFactor), Math.abs(minScaleFactor - startFactor));
// border for faceYes-possibility must be greater that that
- @LOC("THIS,ClassifierTree.C") float maxBorder = 0.999f;
+ @LOC("THIS,ClassifierTree.CUR") float maxBorder = 0.999f;
- @LOC("THIS,ClassifierTree.C") int startPosX = (int) lastCoordinates.getX();
- @LOC("THIS,ClassifierTree.C") int startPosY = (int) lastCoordinates.getX();
+ @LOC("THIS,ClassifierTree.CUR") int startPosX = (int) px;
+ @LOC("THIS,ClassifierTree.CUR") int startPosY = (int) py;
- @LOC("THIS,ClassifierTree.C") int loopidx = 0;
- TERMINATE: for (@LOC("THIS,ClassifierTree.C") float factorDiff = 0.0f; Math.abs(factorDiff) <= maxScaleDifference; factorDiff =
+ @LOC("THIS,ClassifierTree.CUR") int loopidx = 0;
+ TERMINATE: for (@LOC("THIS,ClassifierTree.CUR") float factorDiff = 0.0f; Math.abs(factorDiff) <= maxScaleDifference; factorDiff =
(factorDiff + sgn(factorDiff) * 0.1f) * -1 // we alternate between
// negative and positiv
// factors
) {
if (++loopidx > 1000) {
- return null;
+ px = -1;
+ py = -1;
+ pwidth = -1;
+ pheight = -1;
+ return;
}
- @LOC("THIS,ClassifierTree.C") float factor = startFactor + factorDiff;
+ @LOC("THIS,ClassifierTree.CUR") float factor = startFactor + factorDiff;
if (factor > maxScaleFactor || factor < minScaleFactor)
continue;
// now we calculate the actualDimmension
- @LOC("THIS,ClassifierTree.C") int actualDimmension = (int) (100 * factor);
- @LOC("THIS,ClassifierTree.C") int maxX = imageData.getWidth() - actualDimmension;
- @LOC("THIS,ClassifierTree.C") int maxY = imageData.getHeight() - actualDimmension;
+ @LOC("THIS,ClassifierTree.CUR") int actualDimmension = (int) (100 * factor);
+ @LOC("THIS,ClassifierTree.CUR") int maxX = imageData.getWidth() - actualDimmension;
+ @LOC("THIS,ClassifierTree.CUR") int maxY = imageData.getHeight() - actualDimmension;
- @LOC("THIS,ClassifierTree.C") int maxDiffX = Math.max(Math.abs(startPosX - maxX), startPosX);
- @LOC("THIS,ClassifierTree.C") int maxDiffY = Math.max(Math.abs(startPosY - maxY), startPosY);
+ @LOC("THIS,ClassifierTree.CUR") int maxDiffX =
+ Math.max(Math.abs(startPosX - maxX), startPosX);
+ @LOC("THIS,ClassifierTree.CUR") int maxDiffY =
+ Math.max(Math.abs(startPosY - maxY), startPosY);
- @LOC("CXY") int xidx = 0;
- TERMINATE: for (@LOC("CXY") float xDiff = 0.1f; Math.abs(xDiff) <= maxDiffX; xDiff =
+ @LOC("THIS,ClassifierTree.CUR") int xidx = 0;
+ TERMINATE: for (@LOC("THIS,ClassifierTree.CUR") float xDiff = 0.1f; Math.abs(xDiff) <= maxDiffX; xDiff =
(xDiff + sgn(xDiff) * 0.5f) * -1) {
if (++xidx > 1000) {
- return null;
+ px = -1;
+ py = -1;
+ pwidth = -1;
+ pheight = -1;
+ return;
}
- @LOC("CXY") int xPos = Math.round((float) (startPosX + xDiff));
+ @LOC("THIS,ClassifierTree.CUR") int xPos = Math.round((float) (startPosX + xDiff));
if (xPos < 0 || xPos > maxX)
continue;
- @LOC("CXY") int yidx = 0;
+ @LOC("THIS,ClassifierTree.CUR") int yidx = 0;
// yLines:
- TERMINATE: for (@LOC("CXY") float yDiff = 0.1f; Math.abs(yDiff) <= maxDiffY; yDiff =
+ TERMINATE: for (@LOC("THIS,ClassifierTree.CUR") float yDiff = 0.1f; Math.abs(yDiff) <= maxDiffY; yDiff =
(yDiff + sgn(yDiff) * 0.5f) * -1) {
if (++yidx > 1000) {
- return null;
+ px = -1;
+ py = -1;
+ pwidth = -1;
+ pheight = -1;
+ return;
}
- @LOC("CXY") int yPos = Math.round(startPosY + yDiff);
+ @LOC("THIS,ClassifierTree.CUR") int yPos = Math.round(startPosY + yDiff);
if (yPos < 0 || yPos > maxY)
continue;
// by now we should have a valid coordinate to process which we should
// do now
- @LOC("CXY") boolean backToYLines = false;
- for (@LOC("CXY") int idx = 0; idx < classifiers.length; ++idx) {
- @LOC("CXY") float borderline =
- 0.8f + (idx / (classifiers.length - 1)) * (maxBorder - 0.8f);
+ @LOC("THIS,ClassifierTree.C") boolean backToYLines = false;
+ for (@LOC("THIS,ClassifierTree.CUR") int idx = 0; idx < size; ++idx) {
+ @LOC("THIS,ClassifierTree.CUR") float borderline =
+ 0.8f + (idx / (size - 1)) * (maxBorder - 0.8f);
if (!classifiers[idx].classifyFace(imageData, factor, xPos, yPos, borderline)) {
backToYLines = true;
break;
if (backToYLines) {
continue;
}
- @LOC("OUT") Rectangle2D faceRect =
- new Rectangle2D(xPos * originalImageFactor, yPos * originalImageFactor,
- actualDimmension * originalImageFactor, actualDimmension * originalImageFactor);
- return faceRect;
+ x = xPos * originalImageFactor;
+ y = yPos * originalImageFactor;
+ width = actualDimmension * originalImageFactor;
+ height = actualDimmension * originalImageFactor;
+ return;
}
}
// System.out.println("Time: "+(System.currentTimeMillis()-timeStart)+"ms");
- return null;
+ // return null;
}
return (value < 0 ? -1 : (value > 0 ? +1 : 1));
}
+ @LATTICE("OUT<P,P<ED,ED<V,V<THIS,THIS<IN,V*,THISLOC=THIS,RETURNLOC=OUT,GLOBALLOC=IN")
+ public FaceAndEyePosition getEyePosition(@LOC("IN") Image image) {
+ if (image == null) {
+ return null;
+ }
+
+ @LOC("IN") float originalImageFactor = 1;
+
+ locateFaceRadial(image);
+
+ if (width > image.getWidth() || height > image.getHeight()) {
+ return null;
+ }
+
+ @LOC("OUT") EyePosition eyePosition = null;
+
+ if (x != -1) {
+ @LOC("ED") EyeDetector ed = new EyeDetector(image, x, y, width, height);
+ @LOC("P") Point point = ed.detectEye();
+ if (point != null) {
+ eyePosition = new EyePosition(point.getX(), point.getY());
+ }
+ }
+
+ System.out.println("eyePosition=" + eyePosition);
+
+ @LOC("OUT") FaceAndEyePosition fep = new FaceAndEyePosition(x, y, width, height, eyePosition);
+
+ return fep;
+ }
+
+
}
@LOC("IMG")
double percent;
- public EyeDetector(Image image, Rectangle2D faceRect) {
+ // public EyeDetector(Image image, Rectangle2D faceRect) {
+ public EyeDetector(Image image, double fx, double fy, double fwidth, double fheight) {
- percent = 0.15 * faceRect.getWidth();
+ percent = 0.15 * fwidth;
Rectangle2D adjustedFaceRect =
- new Rectangle2D(faceRect.getX() + percent, faceRect.getY() + percent, faceRect.getWidth()
- - percent, faceRect.getHeight() - 2 * percent);
+ new Rectangle2D(fx + percent, fy + percent, fwidth - percent, fheight - 2 * percent);
+ // percent = 0.15 * faceRect.getWidth();
+ // Rectangle2D adjustedFaceRect =
+ // new Rectangle2D(faceRect.getX() + percent, faceRect.getY() + percent, faceRect.getWidth()
+ // - percent, faceRect.getHeight() - 2 * percent);
width = (int) adjustedFaceRect.getWidth() / 2;
height = (int) adjustedFaceRect.getHeight() / 2;
private int x;
@LOC("POS")
private int y;
- @LOC("POS")
- private Rectangle2D faceRect;
+
+ @LOC("POS") private double facex;
+ @LOC("POS") private double facey;
+ @LOC("POS") private double facewidth;
+ @LOC("POS") private double faceheight;
- public EyePosition(Point p, Rectangle2D faceRect) {
- this(p.x, p.y, faceRect);
- }
+ // private Rectangle2D faceRect;
+
+ // public EyePosition(Point p, Rectangle2D faceRect) {
+ // this(p.x, p.y, faceRect);
+ // }
+ //
+ // public EyePosition(int x, int y, Rectangle2D faceRect) {
+ // this.x = x;
+ // this.y = y;
+ // this.faceRect = faceRect;
+ // }
- public EyePosition(int x, int y, Rectangle2D faceRect) {
+ public EyePosition(int x, int y) {
this.x = x;
this.y = y;
- this.faceRect = faceRect;
}
public int getX() {
@LOC("POS")
private EyePosition eyePosition;
- public FaceAndEyePosition(Rectangle2D facePosition, EyePosition eyePosition) {
- this.facePosition = facePosition;
+ public FaceAndEyePosition(double x, double y, double w, double h, EyePosition eyePosition) {
+ this.facePosition = new Rectangle2D(x, y, w, h);
this.eyePosition = eyePosition;
}
@LOC("IMPL")
private LEAImplementation implementation;
@LOC("LAST")
- private FaceAndEyePosition lastPositions = new FaceAndEyePosition(null, null);
+ private FaceAndEyePosition lastPositions = new FaceAndEyePosition(-1,-1,-1,-1, null);
@LOC("DEV")
private DeviationScanner deviationScanner = new DeviationScanner();
@LOC("CT")
private ClassifierTree classifierTree;
- @LOC("R")
- private Rectangle2D lastRectangle;
-
public LEAImplementation() {
this.loadFaceData();
}
@LATTICE("OUT<V,V<THIS,THIS<IN,V*,THISLOC=THIS,RETURNLOC=OUT")
@PCLOC("THIS")
public FaceAndEyePosition getEyePosition(@LOC("IN") Image image) {
- if (image == null)
- return null;
- @LOC("THIS,LEAImplementation.R") Rectangle2D faceRect =
- classifierTree.locateFaceRadial(image, lastRectangle);
- if (faceRect.getWidth() > image.getWidth() || faceRect.getHeight() > image.getHeight()) {
- return null;
- }
- @LOC("V") EyePosition eyePosition = null;
- if (faceRect != null) {
- lastRectangle = faceRect;
- faceRect = null;
- @LOC("V") Point point = readEyes(image, lastRectangle);
- if (point != null) {
- eyePosition = new EyePosition(point, lastRectangle);
- }
- } else {
- lastRectangle = null;
- }
- System.out.println("eyePosition=" + eyePosition);
-
- return new FaceAndEyePosition(lastRectangle, eyePosition);
- }
-
- @LATTICE("OUT<P,P<IN,OUT<THIS,THISLOC=THIS,RETURNLOC=OUT")
- @PCLOC("P")
- private Point readEyes(@LOC("IN") Image image, @LOC("IN") Rectangle2D rect) {
- @LOC("OUT") EyeDetector ed = new EyeDetector(image, rect);
- return ed.detectEye();
+ return classifierTree.getEyePosition(image);
}
public boolean needsCalibration() {
}
/**
- * This method loads the faceData from a file called facedata.dat which should
- * be within the jar-file
+ * This method loads the faceData from a file called facedata.dat which should be within the
+ * jar-file
*/
private void loadFaceData() {
public String toString(){
return "("+x+","+y+")";
}
+
+ public int getX(){
+ return x;
+ }
+
+ public int getY(){
+ return y;
+ }
}
for (int i = 0; i < scanAreas.length; ++i) {
values[i] = 0l;
- values[i] +=
- image.getIntegralAt(translationX + scanAreas[i].getToX(scaleFactor), translationY
- + scanAreas[i].getToY(scaleFactor));
- values[i] +=
- image.getIntegralAt(translationX + scanAreas[i].getFromX(scaleFactor), translationY
- + scanAreas[i].getFromY(scaleFactor));
-
- values[i] -=
- image.getIntegralAt(translationX + scanAreas[i].getToX(scaleFactor), translationY
- + scanAreas[i].getFromY(scaleFactor));
- values[i] -=
- image.getIntegralAt(translationX + scanAreas[i].getFromX(scaleFactor), translationY
- + scanAreas[i].getToY(scaleFactor));
+ values[i] += image.getIntegralAt(translationX + scanAreas[i].getToX(scaleFactor), translationY + scanAreas[i].getToY(scaleFactor));
+ values[i] += image.getIntegralAt(translationX + scanAreas[i].getFromX(scaleFactor), translationY + scanAreas[i].getFromY(scaleFactor));
+
+ values[i] -= image.getIntegralAt(translationX + scanAreas[i].getToX(scaleFactor), translationY + scanAreas[i].getFromY(scaleFactor));
+ values[i] -= image.getIntegralAt(translationX + scanAreas[i].getFromX(scaleFactor), translationY + scanAreas[i].getToY(scaleFactor));
values[i] = (long) (values[i] / ((float) scanAreas[i].getSize(scaleFactor)));
avg = ((avgItems * avg) + values[i]) / (++avgItems);
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
- *
+ * private Point readEyes( Image image, Rectangle2D rect) {
+ EyeDetector ed = new EyeDetector(image, rect);
+ return ed.detectEye();
+ }
* You should have received a copy of the GNU Lesser General Public License
* along with LEA. If not, see <http://www.gnu.org/licenses/>.
*/
* @author Florian
*/
-public class ClassifierTree {
- private Classifier classifiers[];
+public class ClassifierTree {
- public ClassifierTree(int size) {
+
+ private Classifier[] classifiers;
+
+ double x;
+
+ double y;
+
+ double width;
+
+ double height;
+
+
+ int size;
+
+
+ public ClassifierTree( int size) {
+ this.size = size;
classifiers = new Classifier[size];
+ x = -1;
+ y = -1;
+ width = -1;
+ height = -1;
}
- public void addClassifier(int idx, Classifier c) {
+ public void addClassifier( int idx, Classifier c) {
classifiers[idx] = c;
}
+
/**
* Locates a face by searching radial starting at the last known position. If lastCoordinates are
* null we simply start in the center of the image.
* @return an rectangle representing the actual face position on success or null if no face could
* be detected
*/
-
- public Rectangle2D locateFaceRadial(Image smallImage, Rectangle2D lastCoordinates) {
-
- IntegralImageData imageData = new IntegralImageData(smallImage);
- float originalImageFactor = 1;
-
- if (lastCoordinates == null) {
+
+ public void locateFaceRadial( Image smallImage) {
+
+ double px = x;
+ double py = y;
+ double pwidth = width;
+ double pheight = height;
+
+ x = -1;
+ y = -1;
+ width = -1;
+ height = -1;
+
+ IntegralImageData imageData = new IntegralImageData(smallImage);
+ float originalImageFactor = 1;
+ if (px == -1) {
+ // if(true){
// if we don't have a last coordinate we just begin in the center
- int smallImageMaxDimension = Math.min(smallImage.getWidth(), smallImage.getHeight());
- lastCoordinates =
- new Rectangle2D((smallImage.getWidth() - smallImageMaxDimension) / 2.0,
- (smallImage.getHeight() - smallImageMaxDimension) / 2.0, smallImageMaxDimension,
- smallImageMaxDimension);
- // System.out.println("lastCoordinates=" + lastCoordinates);
+ int smallImageMaxDimension = Math.min(smallImage.getWidth(), smallImage.getHeight());
+
+ px = (smallImage.getWidth() - smallImageMaxDimension) / 2.0;
+ py = (smallImage.getHeight() - smallImageMaxDimension) / 2.0;
+ pwidth = smallImageMaxDimension;
+ pheight = smallImageMaxDimension;
} else {
// first we have to scale the last coodinates back relative to the resized
// image
- lastCoordinates =
- new Rectangle2D((lastCoordinates.getX() * (1 / originalImageFactor)),
- (lastCoordinates.getY() * (1 / originalImageFactor)),
- (lastCoordinates.getWidth() * (1 / originalImageFactor)),
- (lastCoordinates.getHeight() * (1 / originalImageFactor)));
+ px = px * (1 / originalImageFactor);
+ py = py * (1 / originalImageFactor);
+ pwidth = pwidth * (1 / originalImageFactor);
+ pheight = pheight * (1 / originalImageFactor);
}
- float startFactor = (float) (lastCoordinates.getWidth() / 100.0f);
+
+ float startFactor = (float) (pwidth / 100.0f);
// first we calculate the maximum scale factor for our 200x200 image
- float maxScaleFactor = Math.min(imageData.getWidth() / 100f, imageData.getHeight() / 100f);
+ float maxScaleFactor = Math.min(imageData.getWidth() / 100f, imageData.getHeight() / 100f);
// maxScaleFactor = 1.0f;
// we simply won't recognize faces that are smaller than 40x40 px
- float minScaleFactor = 0.5f;
+ float minScaleFactor = 0.5f;
- float maxScaleDifference = Math.max(Math.abs(maxScaleFactor - startFactor), Math.abs(minScaleFactor - startFactor));
+ float maxScaleDifference = Math.max(Math.abs(maxScaleFactor - startFactor), Math.abs(minScaleFactor - startFactor));
// border for faceYes-possibility must be greater that that
- float maxBorder = 0.999f;
+ float maxBorder = 0.999f;
- int startPosX = (int) lastCoordinates.getX();
- int startPosY = (int) lastCoordinates.getX();
+ int startPosX = (int) px;
+ int startPosY = (int) py;
- int loopidx = 0;
- TERMINATE: for (float factorDiff = 0.0f; Math.abs(factorDiff) <= maxScaleDifference; factorDiff =
+ int loopidx = 0;
+ TERMINATE: for ( float factorDiff = 0.0f; Math.abs(factorDiff) <= maxScaleDifference; factorDiff =
(factorDiff + sgn(factorDiff) * 0.1f) * -1 // we alternate between
// negative and positiv
// factors
) {
if (++loopidx > 1000) {
- return null;
+ px = -1;
+ py = -1;
+ pwidth = -1;
+ pheight = -1;
+ return;
}
- float factor = startFactor + factorDiff;
+ float factor = startFactor + factorDiff;
if (factor > maxScaleFactor || factor < minScaleFactor)
continue;
// now we calculate the actualDimmension
- int actualDimmension = (int) (100 * factor);
- int maxX = imageData.getWidth() - actualDimmension;
- int maxY = imageData.getHeight() - actualDimmension;
+ int actualDimmension = (int) (100 * factor);
+ int maxX = imageData.getWidth() - actualDimmension;
+ int maxY = imageData.getHeight() - actualDimmension;
- int maxDiffX = Math.max(Math.abs(startPosX - maxX), startPosX);
- int maxDiffY = Math.max(Math.abs(startPosY - maxY), startPosY);
+ int maxDiffX = Math.max(Math.abs(startPosX - maxX), startPosX);
+ int maxDiffY = Math.max(Math.abs(startPosY - maxY), startPosY);
- int xidx = 0;
- TERMINATE: for (float xDiff = 0.1f; Math.abs(xDiff) <= maxDiffX; xDiff =
+ int xidx = 0;
+ TERMINATE: for ( float xDiff = 0.1f; Math.abs(xDiff) <= maxDiffX; xDiff =
(xDiff + sgn(xDiff) * 0.5f) * -1) {
if (++xidx > 1000) {
- return null;
+ px = -1;
+ py = -1;
+ pwidth = -1;
+ pheight = -1;
+ return;
}
- int xPos = Math.round((float) (startPosX + xDiff));
+ int xPos = Math.round((float) (startPosX + xDiff));
if (xPos < 0 || xPos > maxX)
continue;
- int yidx = 0;
+ int yidx = 0;
// yLines:
- TERMINATE: for (float yDiff = 0.1f; Math.abs(yDiff) <= maxDiffY; yDiff =
+ TERMINATE: for ( float yDiff = 0.1f; Math.abs(yDiff) <= maxDiffY; yDiff =
(yDiff + sgn(yDiff) * 0.5f) * -1) {
if (++yidx > 1000) {
- return null;
+ px = -1;
+ py = -1;
+ pwidth = -1;
+ pheight = -1;
+ return;
}
- int yPos = Math.round(startPosY + yDiff);
+ int yPos = Math.round(startPosY + yDiff);
if (yPos < 0 || yPos > maxY)
continue;
// by now we should have a valid coordinate to process which we should
// do now
- boolean backToYLines = false;
- for (int idx = 0; idx < classifiers.length; ++idx) {
- float borderline = 0.8f + (idx / (classifiers.length - 1)) * (maxBorder - 0.8f);
+ boolean backToYLines = false;
+ for ( int idx = 0; idx < size; ++idx) {
+ float borderline = 0.8f + (idx / (size - 1)) * (maxBorder - 0.8f);
if (!classifiers[idx].classifyFace(imageData, factor, xPos, yPos, borderline)) {
backToYLines = true;
break;
continue;
}
- Rectangle2D faceRect = new Rectangle2D(xPos * originalImageFactor, yPos * originalImageFactor, actualDimmension * originalImageFactor, actualDimmension * originalImageFactor);
-
- return faceRect;
+ x = xPos * originalImageFactor;
+ y = yPos * originalImageFactor;
+ width = actualDimmension * originalImageFactor;
+ height = actualDimmension * originalImageFactor;
+ return;
}
}
- // System.out.println("Time: "+(System.currentTimeMillis()-timeStart)+"ms");
- return null;
}
- private static int sgn(float value) {
+
+
+ private static int sgn( float value) {
return (value < 0 ? -1 : (value > 0 ? +1 : 1));
}
+
+ public FaceAndEyePosition getEyePosition( Image image) {
+ if (image == null) {
+ return null;
+ }
+
+ float originalImageFactor = 1;
+
+ locateFaceRadial(image);
+
+ if (width > image.getWidth() || height > image.getHeight()) {
+ return null;
+ }
+
+ EyePosition eyePosition = null;
+
+ if (x != -1) {
+ EyeDetector ed = new EyeDetector(image, x, y, width, height);
+ Point point = ed.detectEye();
+ if (point != null) {
+ eyePosition = new EyePosition(point.getX(), point.getY());
+ }
+ }
+
+ System.out.println("eyePosition=" + eyePosition);
+
+ FaceAndEyePosition fep = new FaceAndEyePosition(x, y, width, height, eyePosition);
+
+
+ return fep;
+ }
+
+
}
* @author Florian Frankenberger\r
*/\r
\r
+\r
public class DeviationScanner {\r
\r
+ \r
private EyePosition eyePositions[];\r
\r
// LEFT_UP(+1, -1), UP(0, -1), RIGHT_UP(-1, -1), LEFT(+1, 0), NONE(0, 0),\r
eyePositions = new EyePosition[3];\r
}\r
\r
- public void addEyePosition(EyePosition eyePosition) {\r
+ \r
+ public void addEyePosition( EyePosition eyePosition) {\r
\r
// for ( int i = 1; i < 3; i++) {\r
// eyePositions[i - 1] = eyePositions[i];\r
\r
}\r
\r
- //\r
-\r
- public int scanForDeviation(Rectangle2D faceRect) {\r
+ // \r
+ \r
+ \r
+ public int scanForDeviation( Rectangle2D faceRect) {\r
\r
- int deviation = NONE;\r
+ int deviation = NONE;\r
\r
- for (int i = 0; i < 3; i++) {\r
+ for ( int i = 0; i < 3; i++) {\r
if (eyePositions[i] == null) {\r
return deviation;\r
}\r
}\r
\r
- double deviationX = 0;\r
- double deviationY = 0;\r
+ double deviationX = 0;\r
+ double deviationY = 0;\r
\r
- int lastIdx = -1;\r
- for (int i = 0; i < 3; ++i) {\r
+ int lastIdx = -1;\r
+ for ( int i = 0; i < 3; ++i) {\r
if (lastIdx != -1) {\r
deviationX += (eyePositions[i].getX() - eyePositions[lastIdx].getX());\r
deviationY += (eyePositions[i].getY() - eyePositions[lastIdx].getY());\r
lastIdx = i;\r
}\r
\r
- final double deviationPercentX = 0.04;\r
- final double deviationPercentY = 0.04;\r
+ final double deviationPercentX = 0.04;\r
+ final double deviationPercentY = 0.04;\r
\r
deviationX /= faceRect.getWidth();\r
deviationY /= faceRect.getWidth();\r
\r
- int deviationAbsoluteX = 0;\r
- int deviationAbsoluteY = 0;\r
+ int deviationAbsoluteX = 0;\r
+ int deviationAbsoluteY = 0;\r
if (deviationX > deviationPercentX)\r
deviationAbsoluteX = 1;\r
if (deviationX < -deviationPercentX)\r
return deviation;\r
}\r
\r
- public int getDirectionFor(int directionX, int directionY) {\r
+ \r
+ public int getDirectionFor( int directionX, int directionY) {\r
\r
if (directionX == +1 && directionY == -1) {\r
return LEFT_UP;\r
eyePositions = new EyePosition[3];\r
}\r
\r
- public String toStringDeviation(int dev) {\r
+ public String toStringDeviation( int dev) {\r
if (dev == LEFT_UP) {\r
return "LEFT_UP";\r
} else if (dev == UP) {\r
*/\r
public class DummyCaptureDevice implements ICaptureDevice {\r
\r
- /**\r
+ /**\r
* \r
*/\r
- public DummyCaptureDevice() {\r
- // TODO Auto-generated constructor stub\r
- }\r
-\r
- /*\r
- * (non-Javadoc)\r
- * \r
- * @see de.darkblue.lea.ifaces.ICaptureDevice#close()\r
- */\r
- @Override\r
- public void close() {\r
- }\r
-\r
- /*\r
- * (non-Javadoc)\r
- * \r
- * @see de.darkblue.lea.ifaces.ICaptureDevice#getFrameRate()\r
- */\r
- @Override\r
- public int getFrameRate() {\r
- return 15;\r
- }\r
-\r
- /*\r
- * (non-Javadoc)\r
- * \r
- * @see de.darkblue.lea.ifaces.ICaptureDevice#getImage()\r
- */\r
- @Override\r
- public BufferedImage getImage() {\r
- BufferedImage image = new BufferedImage(640, 480, BufferedImage.TYPE_INT_RGB);\r
- Graphics2D g2d = (Graphics2D) image.getGraphics();\r
- g2d.setColor(new Color(255, 255, 255));\r
- g2d.fillRect(0, 0, 639, 479);\r
- return image;\r
- }\r
+ public DummyCaptureDevice() {\r
+ // TODO Auto-generated constructor stub\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see de.darkblue.lea.ifaces.ICaptureDevice#close()\r
+ */\r
+ @Override\r
+ public void close() {\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see de.darkblue.lea.ifaces.ICaptureDevice#getFrameRate()\r
+ */\r
+ @Override\r
+ public int getFrameRate() {\r
+ return 15;\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see de.darkblue.lea.ifaces.ICaptureDevice#getImage()\r
+ */\r
+ @Override\r
+ public BufferedImage getImage() {\r
+ BufferedImage image = new BufferedImage(640, 480, BufferedImage.TYPE_INT_RGB);\r
+ Graphics2D g2d = (Graphics2D)image.getGraphics();\r
+ g2d.setColor(new Color(255, 255, 255));\r
+ g2d.fillRect(0, 0, 639, 479);\r
+ return image;\r
+ }\r
\r
}\r
* @author Florian Frankenberger
*/
+
class EyeDetector {
+
private int width;
-
+
private int height;
-
+
private int[] pixelBuffer;
-
+
double percent;
- public EyeDetector(Image image, Rectangle2D faceRect) {
+ // public EyeDetector(Image image, Rectangle2D faceRect) {
+ public EyeDetector(Image image, double fx, double fy, double fwidth, double fheight) {
- percent = 0.15 * faceRect.getWidth();
- Rectangle2D adjustedFaceRect =
- new Rectangle2D(faceRect.getX() + percent, faceRect.getY() + percent, faceRect.getWidth()
- - percent, faceRect.getHeight() - 2 * percent);
+ percent = 0.15 * fwidth;
+ Rectangle2D adjustedFaceRect = new Rectangle2D(fx + percent, fy + percent, fwidth - percent, fheight - 2 * percent);
+ // percent = 0.15 * faceRect.getWidth();
+ // Rectangle2D adjustedFaceRect =
+ // new Rectangle2D(faceRect.getX() + percent, faceRect.getY() + percent, faceRect.getWidth()
+ // - percent, faceRect.getHeight() - 2 * percent);
width = (int) adjustedFaceRect.getWidth() / 2;
height = (int) adjustedFaceRect.getHeight() / 2;
}
+
public Point detectEye() {
- Point eyePosition = null;
- float brightness = 255f;
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; ++x) {
- int position = y * width + x;
- int[] color = new int[] { (pixelBuffer[position] & 0xFF0000) >> 16, (pixelBuffer[position] & 0x00FF00) >> 8, pixelBuffer[position] & 0x0000FF };
+ Point eyePosition = null;
+ float brightness = 255f;
+ for ( int y = 0; y < height; ++y) {
+ for ( int x = 0; x < width; ++x) {
+ int position = y * width + x;
+ int[] color = new int[] { (pixelBuffer[position] & 0xFF0000) >> 16,(pixelBuffer[position] & 0x00FF00) >> 8, pixelBuffer[position] & 0x0000FF };
// System.out.println("("+x+","+y+")="+color[0]+" "+color[1]+" "+color[2]);
- float acBrightness = getBrightness(color);
+ final float acBrightness = getBrightness(color);
if (acBrightness < brightness) {
eyePosition = new Point(x + (int) percent, y + (int) percent);
return eyePosition;
}
- private static float getBrightness(int[] color) {
- int min = Math.min(Math.min(color[0], color[1]), color[2]);
- int max = Math.max(Math.max(color[0], color[1]), color[2]);
+
+ private static float getBrightness( int[] color) {
+ int min = Math.min(Math.min(color[0], color[1]), color[2]);
+ int max = Math.max(Math.max(color[0], color[1]), color[2]);
return 0.5f * (max + min);
}
* @author Florian Frankenberger
*/
-public class EyePosition {
+public class EyePosition {
+
private int x;
-
+
private int y;
+
+ private double facex;
+ private double facey;
+ private double facewidth;
+ private double faceheight;
- private Rectangle2D faceRect;
+ // private Rectangle2D faceRect;
- public EyePosition(Point p, Rectangle2D faceRect) {
- this(p.x, p.y, faceRect);
- }
+ // public EyePosition(Point p, Rectangle2D faceRect) {
+ // this(p.x, p.y, faceRect);
+ // }
+ //
+ // public EyePosition(int x, int y, Rectangle2D faceRect) {
+ // this.x = x;
+ // this.y = y;
+ // this.faceRect = faceRect;
+ // }
- public EyePosition(int x, int y, Rectangle2D faceRect) {
+ public EyePosition(int x, int y) {
this.x = x;
this.y = y;
- this.faceRect = faceRect;
}
public int getX() {
* @author Florian Frankenberger
*/
+
public class FaceAndEyePosition {
+
private Rectangle2D facePosition;
-
+
private EyePosition eyePosition;
- public FaceAndEyePosition(Rectangle2D facePosition, EyePosition eyePosition) {
- this.facePosition = facePosition;
+ public FaceAndEyePosition(double x, double y, double w, double h, EyePosition eyePosition) {
+ this.facePosition = new Rectangle2D(x, y, w, h);
this.eyePosition = eyePosition;
}
* along with LEA. If not, see <http://www.gnu.org/licenses/>.\r
*/\r
\r
+\r
import java.awt.image.BufferedImage;\r
\r
/**\r
- * Describes a capture device. For now it is only tested with images in <code>640x480</code> at\r
- * <code>RGB</code> or <code>YUV</code> color space.\r
+ * Describes a capture device. For now it is only tested\r
+ * with images in <code>640x480</code> at <code>RGB</code> or <code>YUV</code> color space.\r
* \r
* @author Florian Frankenberger\r
*/\r
public interface ICaptureDevice {\r
\r
- /**\r
- * Returns the frame rate of the image source per second\r
- * \r
- * @return the frame rate (e.g. 15 = 15 frames per second)\r
- */\r
- public int getFrameRate();\r
-\r
- /**\r
- * Will be called a maximum of getFrameRate()-times in a second and returns the actual image of\r
- * the capture device\r
- * \r
- * @return the actual image of the capture device\r
- */\r
- public BufferedImage getImage();\r
-\r
- /**\r
- * LEA calls this when it cleans up. You should put your own cleanup code in here.\r
- */\r
- public void close();\r
+ /**\r
+ * Returns the frame rate of the image source per second\r
+ * \r
+ * @return the frame rate (e.g. 15 = 15 frames per second)\r
+ */\r
+ public int getFrameRate();\r
\r
+ /**\r
+ * Will be called a maximum of getFrameRate()-times in a second and returns\r
+ * the actual image of the capture device\r
+ * \r
+ * @return the actual image of the capture device \r
+ */\r
+ public BufferedImage getImage();\r
+ \r
+ /**\r
+ * LEA calls this when it cleans up. You should put your own cleanup code in here.\r
+ */\r
+ public void close();\r
+ \r
+ \r
}\r
+
public class Image {
+
int width;
-
+
int height;
-
+
int pixel[][];
public Image(int width, int height) {
* @author Florian Frankenberger
*/
+
public class IntegralImageData {
+
private long[][] integral;
-
+
private int width;
-
+
private int hegith;
// private Dimension dimension;
}
- public long getIntegralAt(int x, int y) {
+ public long getIntegralAt( int x, int y) {
return this.integral[x][y];
}
return hegith;
}
- public String toString() {
- super.toString();
- }
-
}
/**
* This is the main class of LEA.
* <p>
- * It uses a face detection algorithm to find an a face within the provided image(s). Then it
- * searches for the eye in a region where it most likely located and traces its position relative to
- * the face and to the last known position. The movements are estimated by comparing more than one
- * movement. If a movement is distinctly pointing to a direction it is recognized and all listeners
- * get notified.
+ * It uses a face detection algorithm to find an a face within the provided
+ * image(s). Then it searches for the eye in a region where it most likely
+ * located and traces its position relative to the face and to the last known
+ * position. The movements are estimated by comparing more than one movement. If
+ * a movement is distinctly pointing to a direction it is recognized and all
+ * listeners get notified.
* <p>
* The notification is designed as observer pattern. You simply call
- * <code>addEyeMovementListener(IEyeMovementListener)</code> to add an implementation of
- * <code>IEyeMovementListener</code> to LEA. When a face is recognized/lost or whenever an eye
- * movement is detected LEA will call the appropriate methods of the listener
+ * <code>addEyeMovementListener(IEyeMovementListener)</code> to add an
+ * implementation of <code>IEyeMovementListener</code> to LEA. When a face is
+ * recognized/lost or whenever an eye movement is detected LEA will call the
+ * appropriate methods of the listener
* <p>
- * LEA also needs an image source implementing the <code>ICaptureDevice</code>. One image source
- * proxy to the <code>Java Media Framework</code> is included ( <code>JMFCaptureDevice</code>).
+ * LEA also needs an image source implementing the <code>ICaptureDevice</code>.
+ * One image source proxy to the <code>Java Media Framework</code> is included (
+ * <code>JMFCaptureDevice</code>).
* <p>
* Example (for using LEA with <code>Java Media Framework</code>):
* <p>
* LEA lea = new LEA(new JMFCaptureDevice(), true);
* </code>
* <p>
- * This will start LEA with the first available JMF datasource with an extra status window showing
- * if face/eye has been detected successfully. Please note that face detection needs about 2 seconds
- * to find a face. After detection the following face detection is much faster.
+ * This will start LEA with the first available JMF datasource with an extra
+ * status window showing if face/eye has been detected successfully. Please note
+ * that face detection needs about 2 seconds to find a face. After detection the
+ * following face detection is much faster.
*
* @author Florian Frankenberger
*/
+
public class LEA {
+
private LEAImplementation implementation;
-
- private FaceAndEyePosition lastPositions = new FaceAndEyePosition(null, null);
-
+
+ private FaceAndEyePosition lastPositions = new FaceAndEyePosition(-1,-1,-1,-1, null);
+
private DeviationScanner deviationScanner = new DeviationScanner();
public LEA() {
}
/**
- * Clears the internal movement buffer. If you just capture some of the eye movements you should
- * call this every time you start recording the movements. Otherwise you may get notified for
- * movements that took place BEFORE you started recording.
+ * Clears the internal movement buffer. If you just capture some of the eye
+ * movements you should call this every time you start recording the
+ * movements. Otherwise you may get notified for movements that took place
+ * BEFORE you started recording.
*/
public void clear() {
// this.imageProcessor.clearDeviationScanner();
}
/**
- * @METHOD To test LEA with the first capture device from the <code>Java Media Framework</code>
- * just start from here.
+ * @METHOD To test LEA with the first capture device from the
+ * <code>Java Media Framework</code> just start from here.
*
* @param args
* @throws Exception
lea.doRun();
}
+
public void doRun() {
- int i = 0;
+ int i = 0;
SSJAVA: while (true) {
- Image image = ImageReader.getImage();
+ Image image = ImageReader.getImage();
if (image == null) {
break;
}
System.out.println("Done.");
}
+
- private void processImage(Image image) {
- FaceAndEyePosition positions = implementation.getEyePosition(image);
+ private void processImage( Image image) {
+ FaceAndEyePosition positions = implementation.getEyePosition(image);
// if (positions.getEyePosition() != null) {
deviationScanner.addEyePosition(positions.getEyePosition());
- int deviation = deviationScanner.scanForDeviation(positions.getFacePosition());// positions.getEyePosition().getDeviation(lastPositions.getEyePosition());
+ int deviation = deviationScanner.scanForDeviation(positions.getFacePosition());// positions.getEyePosition().getDeviation(lastPositions.getEyePosition());
if (deviation != DeviationScanner.NONE) {
System.out.println("deviation=" + deviationScanner.toStringDeviation(deviation));
// notifyEyeMovementListenerEyeMoved(deviation);
* @author Florian Frankenberger
*/
+
public class LEAImplementation {
+
private ClassifierTree classifierTree;
- private Rectangle2D lastRectangle;
public LEAImplementation() {
this.loadFaceData();
}
- public FaceAndEyePosition getEyePosition(Image image) {
- if (image == null)
- return null;
- Rectangle2D faceRect = classifierTree.locateFaceRadial(image, lastRectangle);
- if (faceRect.getWidth() > image.getWidth() || faceRect.getHeight() > image.getHeight()) {
- return null;
- }
- EyePosition eyePosition = null;
- if (faceRect != null) {
- lastRectangle = faceRect;
- faceRect = null;
- Point point = readEyes(image, lastRectangle);
- if (point != null) {
- eyePosition = new EyePosition(point, lastRectangle);
- }
- } else {
- lastRectangle = null;
- }
- System.out.println("eyePosition=" + eyePosition);
-
- return new FaceAndEyePosition(lastRectangle, eyePosition);
- }
-
- private Point readEyes(Image image, Rectangle2D rect) {
- EyeDetector ed = new EyeDetector(image, rect);
- return ed.detectEye();
+
+
+ public FaceAndEyePosition getEyePosition( Image image) {
+ return classifierTree.getEyePosition(image);
}
public boolean needsCalibration() {
+
+
public class Point {
- public int x;
- public int y;
+ public int x;
+ public int y;
public Point(int x, int y) {
this.x = x;
public Point() {
}
-
- public String toString() {
- return "(" + x + "," + y + ")";
+
+ public String toString(){
+ return "("+x+","+y+")";
+ }
+
+ public int getX(){
+ return x;
+ }
+
+ public int getY(){
+ return y;
}
}
+
+
public class Rectangle2D {
- double x;
- double y;
- double width;
- double height;
+ double x;
+ double y;
+ double width;
+ double height;
public Rectangle2D(double x, double y, double w, double h) {
this.x = x;
* @author Florian
*/
+
public class ScanArea {
+
private Point fromPoint;
-
+
private Point toPoint;
-
+
private float size;
/**
- * Imagine you want to classify an image with 100px x 100px what would be the scanarea in this
- * kind of image. That size gets automatically scalled to fit bigger images
+ * Imagine you want to classify an image with 100px x 100px what would be the
+ * scanarea in this kind of image. That size gets automatically scalled to fit
+ * bigger images
*
* @param fromPoint
* @param toPoint
this(new Point(fromX, fromY), new Point(fromX + width, fromY + height));
}
- public int getFromX(float scaleFactor) {
+ public int getFromX( float scaleFactor) {
return (int) (this.fromPoint.x * scaleFactor);
}
- public int getFromY(float scaleFactor) {
+ public int getFromY( float scaleFactor) {
return (int) (this.fromPoint.y * scaleFactor);
}
- public int getToX(float scaleFactor) {
+ public int getToX( float scaleFactor) {
return (int) (this.toPoint.x * scaleFactor);
}
- public int getToY(float scaleFactor) {
+ public int getToY( float scaleFactor) {
return (int) (this.toPoint.y * scaleFactor);
}
- public int getSize(float scaleFactor) {
+ public int getSize( float scaleFactor) {
return (int) (this.size * Math.pow(scaleFactor, 2));
}
// }
public String toString() {
- String str = "";
+ String str = "";
str += "fromPoint=(" + fromPoint.x + "," + fromPoint.y + ")";
str += "toPoint=(" + toPoint.x + "," + toPoint.y + ")";
str += "size=" + size;