private class ConvexityDefect { private Point mStart; private Point mEnd; private Point mDepthPoint; private float mDepth; public Point getStart(){ return mStart; } public Point getEnd(){ return mEnd; } public Point getDepthPoint(){ return mDepthPoint; } public float getDepth(){ return mDepth; } public void setStart(Point start){ this.mStart = start; } public void setEnd(Point end){ this.mEnd = end; } public void setDepthPoint(Point DepthPoint){ this.mDepthPoint = DepthPoint; } public void setDepth(float depth){ this.mDepth = depth; } } public List findConvexityDefects(Mat contour, List hullPts){ List contourPts = new ArrayList(); List defects = new ArrayList(); Converters.Mat_to_vector_Point(contour, contourPts); if(contourPts.size() < 4 || hullPts.size() < 3) { // Error: Contour size must be >= 4 and convex hull size must be >= 3 return null; } // Co-Orientation of Contour and it's Hull int sign = 0; int index1, index2, index3; Point pos, hull_cur, contour_cur; pos = hullPts.get(0); index1 = contourPts.indexOf(pos); pos = hullPts.get(1); index2 = contourPts.indexOf(pos); pos = hullPts.get(2); index3 = contourPts.indexOf(pos); sign += (index2 > index1) ? 1 : 0; sign += (index3 > index2) ? 1 : 0; sign += (index1 > index3) ? 1 : 0; if(sign == 1) // 0: same orientation 1: reverse orientation Collections.reverse(hullPts); // Cycle through the contour and hull for( int i = 0; i < hullPts.size(); i++ ) { double dx0, dy0; double depth = 0, scale; boolean is_defect = false; Point hull_next; ConvexityDefect defect = new ConvexityDefect(); hull_cur = hullPts.get(i); if(i + 1 == hullPts.size()) // Caculate the defect between the last hull point and the first hull_next = hullPts.get(0); // First point of the hull else hull_next = hullPts.get(i+1); dx0 = hull_next.x - hull_cur.x; dy0 = hull_next.y - hull_cur.y; assert( dx0 != 0 || dy0 != 0 ); scale = 1/Math.sqrt(dx0*dx0 + dy0*dy0); defect.setStart(hull_cur); defect.setEnd(hull_next); // Cycle through the contour till next hull point for( int k = contourPts.indexOf(hullPts.get(i)); k < contourPts.size() ; k++ ) { contour_cur = contourPts.get(k); // Next contour point between the 2 hull points if(contour_cur.equals(hull_next)) // If we have reached the second hull point, stop cycling through the contour break; else { if(k + 1 == contourPts.size()) // If the contour reached the end, start from the first point { k = 0; // Reset the index to the first point of the contour contour_cur = contourPts.get(k); // Next contour point between the 2 hull points if(contour_cur.equals(hull_next)) break; } // Compute distance from current point to the hull edge double dx = contour_cur.x - hull_cur.x; double dy = contour_cur.y - hull_cur.y; // Compute depth double dist = Math.abs(-dy0*dx + dx0*dy) * scale; if( dist > depth ) { depth = dist; defect.setDepthPoint(contour_cur); defect.setDepth((float)depth); is_defect = true; } } } if(is_defect) { defects.add(defect); is_defect = false; } } return defects; }