void MarkerDetector::findCandidates ( const ContoursVector& contours, std::vector<Marker>& detectedMarkers ) { std::vector<cv::Point> approxCurve; std::vector<Marker> possibleMarkers; // For each contour, analyze if it is a parallelepiped likely to be the marker for (size_t i=0; i<contours.size(); i++) { // Approximate to a polygon double eps = contours[i].size() * 0.05; cv::approxPolyDP(contours[i], approxCurve, eps, true); // We interested only in polygons that contains only four points if (approxCurve.size() != 4) continue; // And they have to be convex if (!cv::isContourConvex(approxCurve)) continue; // Ensure that the distance between consecutive points is large enough float minDist = std::numeric_limits<float>::max(); for (int i = 0; i < 4; i++) { cv::Point side = approxCurve[i] - approxCurve[(i+1)%4]; float squaredSideLength = side.dot(side); minDist = std::min(minDist, squaredSideLength); } // Check that distance is not very small if (minDist < m_minContourLengthAllowed) continue; // All tests are passed. Save marker candidate: Marker m; for (int i = 0; i<4; i++) m.points.push_back( cv::Point2f(approxCurve[i].x,approxCurve[i].y) ); // Sort the points in anti-clockwise order // Trace a line between the first and second point. // If the third point is at the right side, then the points are anti-clockwise cv::Point v1 = m.points[1] - m.points[0]; cv::Point v2 = m.points[2] - m.points[0]; double o = (v1.x * v2.y) - (v1.y * v2.x); if (o < 0.0) //if the third point is in the left side, then sort in anti-clockwise order std::swap(m.points[1], m.points[3]); possibleMarkers.push_back(m); } // Remove these elements which corners are too close to each other. // First detect candidates for removal: std::vector< std::pair<int,int> > tooNearCandidates; for (size_t i=0;i<possibleMarkers.size();i++) { const Marker& m1 = possibleMarkers[i]; //calculate the average distance of each corner to the nearest corner of the other marker candidate for (size_t j=i+1;j<possibleMarkers.size();j++) { const Marker& m2 = possibleMarkers[j]; float distSquared = 0; for (int c = 0; c < 4; c++) { cv::Point v = m1.points[c] - m2.points[c]; distSquared += v.dot(v); } distSquared /= 4; if (distSquared < 100) { tooNearCandidates.push_back(std::pair<int,int>(i,j)); } } } // Mark for removal the element of the pair with smaller perimeter std::vector<bool> removalMask (possibleMarkers.size(), false); for (size_t i=0; i<tooNearCandidates.size(); i++) { float p1 = perimeter(possibleMarkers[tooNearCandidates[i].first ].points); float p2 = perimeter(possibleMarkers[tooNearCandidates[i].second].points); size_t removalIndex; if (p1 > p2) removalIndex = tooNearCandidates[i].second; else removalIndex = tooNearCandidates[i].first; removalMask[removalIndex] = true; } // Return candidates detectedMarkers.clear(); for (size_t i=0;i<possibleMarkers.size();i++) { if (!removalMask[i]) detectedMarkers.push_back(possibleMarkers[i]); } }
void dgConvexHull4d::InsertNewVertex(dgInt32 vertexIndex, dgListNode* const frontFace, dgList<dgListNode*>& deletedFaces, dgList<dgListNode*>& newFaces) { dgAssert (Sanity()); dgList<dgListNode*> stack(GetAllocator()); dgInt32 mark = IncMark(); stack.Append(frontFace); dgHullVector* const hullVertexArray = &m_points[0]; const dgBigVector& p = hullVertexArray[vertexIndex]; while (stack.GetCount()) { dgList<dgListNode*>::dgListNode* const stackNode = stack.GetLast(); dgListNode* const node = stackNode->GetInfo(); stack.Remove(stackNode); dgConvexHull4dTetraherum* const face = &node->GetInfo(); if ((face->GetMark() != mark) && (face->Evalue(hullVertexArray, p) > dgFloat64(0.0f))) { #ifdef _DEBUG for (dgList<dgListNode*>::dgListNode* deleteNode = deletedFaces.GetFirst(); deleteNode; deleteNode = deleteNode->GetNext()) { dgAssert (deleteNode->GetInfo() != node); } #endif deletedFaces.Append(node); face->SetMark(mark); for (dgInt32 i = 0; i < 4; i ++) { dgListNode* const twinNode = (dgListNode*)face->m_faces[i].m_twin; dgAssert (twinNode); dgConvexHull4dTetraherum* const twinFace = &twinNode->GetInfo(); if (twinFace->GetMark() != mark) { stack.Append(twinNode); } } } } dgTree<dgListNode*, dgInt32> perimeter(GetAllocator()); for (dgList<dgListNode*>::dgListNode* deleteNode = deletedFaces.GetFirst(); deleteNode; deleteNode = deleteNode->GetNext()) { dgListNode* const deleteTetraNode = deleteNode->GetInfo(); dgConvexHull4dTetraherum* const deletedTetra = &deleteTetraNode->GetInfo(); dgAssert (deletedTetra->GetMark() == mark); for (dgInt32 i = 0; i < 4; i ++) { dgListNode* const twinNode = deletedTetra->m_faces[i].m_twin; dgConvexHull4dTetraherum* const twinTetra = &twinNode->GetInfo(); if (twinTetra->GetMark() != mark) { if (!perimeter.Find(twinTetra->m_uniqueID)) { perimeter.Insert(twinNode, twinTetra->m_uniqueID); } } deletedTetra->m_faces[i].m_twin = NULL; } } dgList<dgListNode*> coneList(GetAllocator()); dgTree<dgListNode*, dgInt32>::Iterator iter (perimeter); for (iter.Begin(); iter; iter ++) { dgListNode* const perimeterNode = iter.GetNode()->GetInfo(); dgConvexHull4dTetraherum* const perimeterTetra = &perimeterNode->GetInfo(); for (dgInt32 i = 0; i < 4; i ++) { dgConvexHull4dTetraherum::dgTetrahedrumFace* const perimeterFace = &perimeterTetra->m_faces[i]; if (perimeterFace->m_twin->GetInfo().GetMark() == mark) { dgListNode* const newNode = AddFace (vertexIndex, perimeterFace->m_index[0], perimeterFace->m_index[1], perimeterFace->m_index[2]); newFaces.Addtop(newNode); dgConvexHull4dTetraherum* const newTetra = &newNode->GetInfo(); newTetra->m_faces[2].m_twin = perimeterNode; perimeterFace->m_twin = newNode; coneList.Append (newNode); } } } for (dgList<dgListNode*>::dgListNode* coneNode = coneList.GetFirst(); coneNode->GetNext(); coneNode = coneNode->GetNext()) { dgListNode* const coneNodeA = coneNode->GetInfo(); for (dgList<dgListNode*>::dgListNode* nextConeNode = coneNode->GetNext(); nextConeNode; nextConeNode = nextConeNode->GetNext()) { dgListNode* const coneNodeB = nextConeNode->GetInfo(); LinkSibling (coneNodeA, coneNodeB); } } }
bool DetectPolygons::processFrameContainer(BaseFrameContainer *frm, BaseFrameSource *frameSource) { Shapes* shapes = frm->getShapes(); std::vector<Point> approxCurve; unsigned int size = 0; ///for each contour, analyze if it is a paralelepiped likely to be the marker for (unsigned int i=0;i<shapes->getContours().size();i++) { unsigned int contourSize = shapes->getContours()[i].size(); //check it is a possible element by first checking is has enough points if (contourSize>(unsigned int)(frm->getFrame()->getMat().cols /15)) { //approximate to a polygon - 1. limit slozitosti (pocet bodu krat cislo vs konstanta), 2. uzavreny double complexity = double(contourSize)*complexityKoef; complexity = complexity > maxComplexity ? maxComplexity : (complexity < minComplexity ? minComplexity : complexity); cv::approxPolyDP( cv::Mat (shapes->getContours()[i]),approxCurve , complexity , onlyClosed); size = approxCurve.size(); unsigned int one, two; if (approxCurve.size() >= 3) { // remove inline points for (unsigned int i = 0; i < size; i++) { one = (i + 1)%size; two = (i + 2)%size; // rozdil smernic double x1 = approxCurve[i].x, y1 = approxCurve[i].y, x2 = approxCurve[one].x, y2 = approxCurve[one].y, x3 = approxCurve[two].x, y3 = approxCurve[two].y; float k = std::abs(((y2-y1)/(x2-x1)) - ((y3-y1)/(x3-x1))); float d1 = std::sqrt((float) (approxCurve[i].x-approxCurve[one].x)*(approxCurve[i].x-approxCurve[one].x) + (approxCurve[i].y-approxCurve[one].y)*(approxCurve[i].y-approxCurve[one].y)); float d2 = std::sqrt((float) (approxCurve[i].x-approxCurve[two].x)*(approxCurve[i].x-approxCurve[two].x) + (approxCurve[i].y-approxCurve[two].y)*(approxCurve[i].y-approxCurve[two].y)); // if angle is too small or points are too close if (k < 0.2 || d1 < 0.04*d2) { approxCurve.erase(approxCurve.begin()+one); size--; } } } if (size >= minimalPolygonLines && size <= maximalPolygonLines) { //and is convex if (!onlyConvex || cv::isContourConvex(Mat (approxCurve))) { float minDist=1e10; if (minDistance > 0) { for (int i=0;i<size;i++) { float d= std::sqrt((float) (approxCurve[i].x-approxCurve[(i+1)%size].x)*(approxCurve[i].x-approxCurve[(i+1)%size].x) + (approxCurve[i].y-approxCurve[(i+1)%size].y)*(approxCurve[i].y-approxCurve[(i+1)%size].y)); if (d<minDist) minDist=d; } } if (minDist>=minDistance) { shapes->getMarkers().push_back(Marker()); for (unsigned int i=0;i<size;i++) { shapes->getMarkers().back().push_back( Point2f(approxCurve[i].x,approxCurve[i].y)); } } } } } } /// remove these elements whise corners are too close to each other //first detect candidates size = shapes->getMarkers().size(); if (minimalPolygonLines==4 && maximalPolygonLines == 4) { for (unsigned int i=0;i<shapes->getMarkers().size();i++) { //trace a line between the first and second point. //if the thrid point is at the right side, then the points are anti-clockwise double dx1 = shapes->getMarkers()[i][1].x - shapes->getMarkers()[i][0].x; double dy1 = shapes->getMarkers()[i][1].y - shapes->getMarkers()[i][0].y; double dx2 = shapes->getMarkers()[i][2].x - shapes->getMarkers()[i][0].x; double dy2 = shapes->getMarkers()[i][2].y - shapes->getMarkers()[i][0].y; double o = (dx1*dy2)-(dy1*dx2); if (o < 0.0) //if the third point is in the left side, then sort in anti-clockwise order { swap(shapes->getMarkers()[i][1],shapes->getMarkers()[i][3]); } } } vector<pair<int,int> > TooNearCandidates; for (unsigned int i=0;i < size;i++) { // cout<<"Marker i="<<i<<MarkerCanditates[i]<<endl; //calculate the average distance of each corner to the nearest corner of the other marker candidate for (unsigned int j=i+1;j<size;j++) { unsigned int vertexCount = shapes->getMarkers()[i].size(); if (vertexCount == shapes->getMarkers()[j].size()) { float dist=0; for (unsigned int c=0;c<vertexCount;c++) dist+= std::sqrt( (shapes->getMarkers()[i][c].x-shapes->getMarkers()[j][c].x)*(shapes->getMarkers()[i][c].x-shapes->getMarkers()[j][c].x)+(shapes->getMarkers()[i][c].y-shapes->getMarkers()[j][c].y)*(shapes->getMarkers()[i][c].y-shapes->getMarkers()[j][c].y)); dist/=vertexCount; //if distance is too small if (dist< 14) { TooNearCandidates.push_back(pair<int,int>(i,j)); } } } } //mark for removal the element of the pair with smaller perimeter vector<bool> toRemove (shapes->getMarkers().size(),false); for (unsigned int i=0;i<TooNearCandidates.size();i++) { if ( perimeter(shapes->getMarkers()[TooNearCandidates[i].first ])>perimeter(shapes->getMarkers()[ TooNearCandidates[i].second] )) toRemove[TooNearCandidates[i].second]=true; else toRemove[TooNearCandidates[i].first]=true; } //remove the invalid ones removeElements(shapes->getMarkers(),toRemove); return true; }
int main() { struct Square mainSquare = {4,0,0}; area(&mainSquare); perimeter(&mainSquare); }
int triplePerimeterCmp(const void * lhs, const void * rhs) { return perimeter(*(triple **)lhs) - perimeter(*(triple **)rhs); }
/* TODO - label_contour is called two times; only once suffices */ AnimalExport ImgPUInt32 * msskl_difference(ann_img *aimg) { ImgPUInt32 *imcont, *immsskel, *imseed, *imperim; puint32 *seed, *cont, *perim, *pred, *label, *msskel, maxd1, maxd2, MaxD; int r,c,i,j,k,qx,qy,p,q, d1,d2, *idxlut,n; r = aimg->label->rows; c = aimg->label->cols; n = r*c; idxlut = aimg->label->lut; imcont = label_contour(aimg->img); imperim = perimeter(aimg->img); immsskel = new_img_puint32(r,c); imseed = root_map(aimg->pred); seed = imseed->data; cont = imcont->data; perim = imperim->data; msskel = immsskel->data; pred = aimg->pred->data; label = aimg->label->data; MaxD = 0; for (i=0; i<r; i++) for (j=0; j<c; j++) { p = index1(i,j,idxlut); // @@@ why eliminate the contours?? if (pred[p] != (unsigned)p) {/* Eliminates the contours and considers the side option */ maxd1 = maxd2 = 0; for (k=0; k < 4; k++) { qy = n4[k][0] + i; qx = n4[k][1] + j; if (valid_pixel(r,c,qx,qy)) { q = index1(qy,qx,idxlut); if (cont[seed[p]] == cont[seed[q]]) { // not a SKIZ d2 = label[q] - label[p]; if (d2 > (int)perim[seed[p]]-d2) d2 = (int)perim[seed[p]]-d2; if (d2 > (int)maxd2) maxd2 = (unsigned)d2; } else { // a SKIZ d1 = cont[seed[q]] - cont[seed[p]]; if (d1 > (int)maxd1) maxd1 = (unsigned)d1; } } } if (maxd1 > 0) msskel[p] = UINT_MAX; else { msskel[p] = maxd2; if (msskel[p] > MaxD) MaxD = msskel[p]; } } } for (p=0; p < n; p++) if (msskel[p] == UINT_MAX) msskel[p] = MaxD + 1; imfree_puint32(&imcont); imfree_puint32(&imperim); imfree_puint32(&imseed); return immsskel; }
//Compute continuity with brep2. int MGSBRep::continuity( // Reuturn value is the continuity. const MGSBRep& brep2, // Input second SBRep int is_u1, // Input if u-direction of this. int is_u2, // Input if u-direction of brep2. int opposite, // Input if parameter direction of which2 is equal or not. int& which1, // Outputs which perimeter(which1) of this is int& which2, // connected to which(which2) of brep2. // These are valid only when continuity>=0. double& ratio // Ratio of 1st derivatives of the two surfaces will // be returned. // ratio= d2/d1, where d1=1st deriv of this and d2=of brep2 ) const // Function's return value is: // -1: G(-1) continuity, i.e. two surfaces are discontinuous. // 0: G0 continuity, i.e. two surfaces are connected, // but tangents are discontinuous // 1: G1 continuity, i.e. two surfaces are connected, // and tangents are also continuous. // 2: G2 continuity, i.e. two surfaces are connected, // and tangents and curvatures are also continuous. { size_t i,j,k,i2; int incrmnt; double ratio2; int which; int cont, contold; size_t dim1=sdim(), dim2=brep2.sdim(); size_t ns1,nt1, ns2,nt2; MGLBRep p1a, p1b, p2a, p2b; // Test if perimeter of this is continuous to perimeter brep2. const MGKnotVector *s1,*s2,*t1,*t2; if(is_u1){ which1=0; s1=&knot_vector_u(); t1=&knot_vector_v(); p1a=perimeter(0); p1b=perimeter(2); } else{ which1=1; s1=&knot_vector_v(); t1=&knot_vector_u(); p1a=perimeter(1); p1b=perimeter(3); } if(is_u2){ which2=0; s2=&(brep2.knot_vector_u()); t2=&(brep2.knot_vector_v()); p2a=brep2.perimeter(0); p2b=brep2.perimeter(2); } else{ which2=1; s2=&(brep2.knot_vector_v()); t2=&(brep2.knot_vector_u()); p2a=brep2.perimeter(1); p2b=brep2.perimeter(3); } ns1=(*s1).bdim(); ns2=(*s2).bdim(); nt1=(*t1).bdim(); nt2=(*t2).bdim(); cont=0; // 1. Test if positional data of two perimeters are equal. if(opposite){ p2a.negate(); p2b.negate();} if (p1a.line_bcoef()==p2a.line_bcoef()){ cont=1;} else if(p1a.line_bcoef()==p2b.line_bcoef()){ which2+=2; cont=1;} else if(p1b.line_bcoef()==p2a.line_bcoef()){ which1+=2; cont=1;} else if(p1b.line_bcoef()==p2b.line_bcoef()){ which1+=2; which2+=2; cont=1;} if(cont==0) return -1; // There exists a possibility of continuity 1. // 2. Test if derivatives along v direction are equal. i2=0; incrmnt=1; if(opposite) {i2=ns2-1; incrmnt=-1;} MGBPointSeq b1(nt1,dim1), b2(nt2,dim2); contold=0; for(i=0; i<ns1; i++){ if(is_u1){ for(j=0; j<nt1; j++) for(k=0; k<dim1; k++) b1(j,k)=coef(i,j,k); } else{ for(j=0; j<nt1; j++) for(k=0; k<dim1; k++) b1(j,k)=coef(j,i,k); } if(is_u2){ for(j=0; j<nt2; j++) for(k=0; k<dim2; k++) b2(j,k)=brep2.coef(i2,j,k); } else{ for(j=0; j<nt2; j++) for(k=0; k<dim2; k++) b2(j,k)=brep2.coef(j,i2,k); } i2=i2+incrmnt; MGLBRep lb1(*t1,b1), lb2(*t2, b2); cont=lb1.continuity(lb2,which,ratio2); if(cont<=0) return 0; //Continuity is C0. if(contold==0) {contold=cont; ratio=ratio2;} else{ if(!MGREqual2(ratio2,ratio)) return 0; //Continuity is C0. else if(contold>cont) contold=cont; } } return contold; }
double QgsTriangle::inscribedRadius() const { return ( 2.0 * area() / perimeter() ); }
/// As used by OpenCV, return value in [0, 1] - requires contour double circularity() const { auto perim = perimeter(); return 4 * CV_PI * area() / (perim * perim); }
bool Rectangle::operator>(Rectangle & rect2){ if(area()>rect2.area() && perimeter()>rect2.perimeter()) return true; return false; }
double Shape :: areaToPerimeter()const { return area()/perimeter(); }