Vector<T, N> getNearestPoint(const LineSegment<T, N>& line, const Vector<T, N>& point) { double divisor = getLengthSquared(line.getVector()); double t = (point - line.getStart()) * line.getVector() / divisor; return line.getPointAtT(getClamped(t, 0.0, 1.0)); }
Vector<T, 2> getRelativePosition(const LineSegment<T, 2>& line, const Vector<T, 2>& point) { auto lv = line.getVector(); double len = getLengthSquared(lv); auto pv = point - line.getStart(); return vector2<T>(lv * pv / len, getNormal(lv) * pv / len); }
void CalibrationRecorder::processImage () { lastMarkerValid=false; double sensitivity = (static_cast<double>(panel->sensitivity)+100.0)/100.0; RGBTuple red = { 255,0,0 }; RGBTuple green = { 0,255,0 }; RGBTuple yellow = { 255,255,0 }; RGBTuple blue = { 0,0,255 }; Painter paint (*image); switch (mode) { case redScreen: setPixelsetAll (*regionBefore, image->getWidth(), image->getHeight()); regionAfter->clear(); findReddishPixels (*regionAfter, *image, sensitivity); drawPixelset (*image, *regionAfter, yellow); break; case greenScreen: regionWork->clear(); regionAfter->clear(); findGreenishPixels (*regionWork, *image, sensitivity); intersectSortedSets (*regionAfter, *regionBefore, *regionWork); drawPixelset (*image, *regionAfter, yellow); break; case blueScreen: regionWork->clear(); regionAfter->clear(); findBluishPixels (*regionWork, *image, sensitivity); intersectSortedSets (*regionAfter, *regionBefore, *regionWork); drawPixelset (*image, *regionAfter, yellow); break; case redMarker: regionWork->clear(); regionAfter->clear(); findReddishPixels (*regionWork, *image, sensitivity); intersectSortedSets (*regionAfter, *regionBefore, *regionWork); drawPixelset (*image, *regionAfter, yellow); gravityCenter = centerOfGravity (*regionAfter); if (gravityCenter.x==0 && gravityCenter.y==0) gravityCenter=Vec(-1000,-1000); // fuer den Fall dass kein roter Bereich gefunden wurde paint.setColor (blue); paint.markCrosshair (static_cast<int>(gravityCenter.x+0.5), static_cast<int>(gravityCenter.y+0.5), 10); break; case blackMarker: { GrayLevelImage ggsrc (*image); std::deque<std::deque<ImageCoordinate> > lines; std::deque<std::deque<ImageCoordinate> > linesC; canny (lines, ggsrc, 5, 6, 20); for (unsigned int i=0; i<lines.size(); i++) { deque<unsigned int> breakpoints; breakLine (breakpoints, lines[i]); deque<deque<ImageCoordinate> > lines2; splitLineSorted (lines2, lines[i], breakpoints); for (unsigned int j=0; j<lines2.size(); j++) { if (lines2[j].size()>5) { deque<ImageCoordinate>::iterator it1=lines2[j].begin(); deque<ImageCoordinate>::iterator it2=lines2[j].end(); if (isAround (gravityCenter, 50, it1, it2)) { deque<ImageCoordinate> nl; linesC.push_back (nl); linesC.back().assign (it1, it2); } } } } if (linesC.size()>=4) { sort (linesC.begin(), linesC.end(), linelencomp); // beste Kombination der 4 Linien suchen unsigned int linesNum = (linesC.size()<8 ? linesC.size() : 8); Vec orientation [8]; for (unsigned int i=0; i<linesNum; i++) orientation[i]=(linesC[i].front().toVec()-linesC[i].back().toVec()).normalize(); unsigned int b1=99, b2=99, b3=99, b4=99; unsigned bestSolution = 1000; Vec intersection; for (unsigned int i1=0; i1<linesNum; i1++) { for (unsigned int i2=i1+1; i2<linesNum; i2++) { double orientationMatch1 = abs(orientation[i1]*orientation[i2]); if (orientationMatch1<0.5) continue; // Kanten sind mehr als 60Grad auseinander double minimalDistance1 = minDist (linesC[i1], linesC[i2], orientation[i1]*orientation[i2]); if (minimalDistance1>20) continue; // Kanten sind zu weit voneinander entfernt std::deque<ImageCoordinate> pxl1 = linesC[i1]; pxl1.insert (pxl1.end(), linesC[i2].begin(), linesC[i2].end()); LineSegment ls1 = estimateLineSegment (pxl1.begin(), pxl1.end()); Line l1 (ls1.getStart(), ls1.getEnd()); Vec dir1 = (ls1.getStart()-ls1.getEnd()).normalize(); for (unsigned int i3=0; i3<linesNum; i3++) if (i3!=i1 && i3!=i2) { for (unsigned int i4=i3+1; i4<linesNum; i4++) if (i4!=i1 && i4!=i2) { try{ double orientationMatch2 = abs(orientation[i3]*orientation[i4]); if (orientationMatch1+orientationMatch2<1.5) continue; // Kanten sind zu weit auseinander double minimalDistance2 = minDist (linesC[i3], linesC[i4], orientation[i1]*orientation[i2]); if (minimalDistance1+minimalDistance2>30) continue; // Kanten sind zu weit voneinander entfernt std::deque<ImageCoordinate> pxl2 = linesC[i3]; pxl2.insert (pxl2.end(), linesC[i4].begin(), linesC[i4].end()); LineSegment ls2 = estimateLineSegment (pxl2.begin(), pxl2.end()); Line l2 (ls2.getStart(), ls2.getEnd()); Vec norm2 = (ls2.getStart()-ls2.getEnd()).normalize().rotate_quarter(); double mm = dir1*norm2; if (mm<0.5) continue; // Kanten bilden kein Kreuz Vec pi = intersect (l1, l2); double md=1e300; for (unsigned int i=0; i<regionAfter->size(); i++) { double d=((*regionAfter)[i].toVec()-pi).length(); if (d<md) md=d; } if (md>5) continue; // Punkt ausserhalb des roten Kreises if (i1+i2+i3+i4<bestSolution) { bestSolution=i1+i2+i3+i4; intersection=pi; b1=i1; b2=i2; b3=i3; b4=i4; } }catch(invalid_argument&){;} } } } } for (unsigned int i=0; i<linesC.size(); i++) { LineSegment ls = estimateLineSegment (linesC[i].begin(), linesC[i].end()); bool sel = (i==b1 || i==b2 || i==b3 || i==b4); drawLine (*image, ls.getStart(), ls.getEnd(), (sel ? red : green), yellow); } if (bestSolution<1000) { cerr << "Schnittpunkt: " << intersection << endl; paint.setColor (blue); paint.markRect (static_cast<int>(intersection.x+0.5), static_cast<int>(intersection.y+0.5), 5); CalibrationMarker mk; mk.truePosition=trueMarkerPosition; mk.imagePosition=intersection; mk.imageNumber=imageNumber; markers.push_back (mk); } else { cerr << "Problem: die laengsten Linienstuecke bilden kein Kreuz\n"; } } else { cerr << "Problem: nur " << linesC.size() << " Linienstuecke gefunden\n"; } break; } default: // nothing, just display image break; } }
LineSegment<T, N> getReverse(const LineSegment<T, N>& line) { return LineSegment<T, N>(line.getEnd(), line.getStart()); }
explicit Line(const LineSegment<U, N>& ls) : m_Point(ls.getStart()), m_Vector(ls.getVector()) {}