猿问

c# - 如何按顺时针顺序对 4 个点的列表进行排序?

我在 c# 中使用 opencv 来检测网络摄像头图像中的轮廓。如果轮廓有 4 个点,我想用它来使用 opencv 的getPerspective和warpPerspective. 职能。


这是获得这4点的代码:


    Imgproc.approxPolyDP(perimMat,polyMat,0.005 * perim, true); //get contour of the current detected perimeter as polyMat

    List<Point> polyMatList = polyMat.toList(); //convert it to a list of points

    if (polyMatList.Count == 4){ //this contour has 4 points, we can use it for getting perspective

      Debug.Log("p1x: " + polyMatList[0].x + "p1y: " + polyMatList[0].y); //example log: p1x: 203,p1y: 111

    }

所以现在我有了这个点列表,我需要确保它是按左上角、右上角、右下角、左下角的顺序排列的,这样我就可以在getPerspective. 我该怎么做呢?


我看过其他语言的例子,但他们通常使用 numpy 之类的东西来进行排序。我对 C# 有点陌生(因为 Unity 使用它),但我假设有一些辅助方法我可以以某种方式借鉴。


到目前为止,这个要点一直是我调整视角的主要指南,该for_point_warp功能似乎提供了一个不错的指南。我只是不知道 c# 等价物。


当年话下
浏览 510回答 2
2回答

青春有我

//Begin by sorting your list by y values using List.sort()polyMatList.sort( (pnt_a, pnt_b) => pnt_b.y - pnt_a.y ); // points 0 & 1 will by definition be your top points and points 2, 3 will be definition be your bottom points.// now your top 2 points may be out of order since we only sorted by y in the previous stepPoint tempPoint;if(polyMatList[0].x > polyMatList[1].x){&nbsp; &nbsp;tempPoint = polyMatList[0];&nbsp; &nbsp;polyMatList[0] = polyMatList[1];&nbsp; &nbsp;polyMatList[1] = tempPoint ;}// same goes for your bottom two points&nbsp;if(polyMatList[2].x > polyMatList[3].x){&nbsp; &nbsp;tempPoint = polyMatList[2];&nbsp; &nbsp;polyMatList[2] = polyMatList[3];&nbsp; &nbsp;polyMatList[3] = tempPoint ;}//now your list will be ordered tl, tr, bl, br&nbsp;

函数式编程

这是我根据本教程实现的(尽管我确信我可以做一些更优雅的事情)。polyMat.convertTo(orientationMat, CvType.CV_32S); //conver MatOfPoint2f back to MatofPoint so it can be drawn//sort by y valpolyMatList = polyMatList.OrderBy(p => p.x).ToList();List<Point> leftmostPts = new List<Point>();leftmostPts.Add(polyMatList[0]);leftmostPts.Add(polyMatList[1]);List<Point> rightmostPts = new List<Point>();rightmostPts.Add(polyMatList[2]);rightmostPts.Add(polyMatList[3]);//we now have a top left pointleftmostPts = leftmostPts.OrderBy(p => p.y).ToList();//calculate distance from top left to rightmost 2 points:double dX0 = rightmostPts[0].x - leftmostPts[0].x;double dY0 = rightmostPts[0].y - leftmostPts[0].y;double d0 = Math.Sqrt(dX0 * dX0 + dY0 * dY0);&nbsp;double dX1 = rightmostPts[1].x - leftmostPts[0].x;double dY1 = rightmostPts[1].y - leftmostPts[0].y;double d1 = Math.Sqrt(dX1 * dX1 + dY1 * dY1);List<Point> orderedPolyMat = new List<Point>();orderedPolyMat.Add(leftmostPts[0]);if (d0 > d1){ //greatest distance between right two points will be bottom right&nbsp; &nbsp; orderedPolyMat.Add(rightmostPts[1]);&nbsp; &nbsp; orderedPolyMat.Add(rightmostPts[0]);} else {&nbsp; &nbsp; orderedPolyMat.Add(rightmostPts[0]);&nbsp; &nbsp; orderedPolyMat.Add(rightmostPts[1]);}orderedPolyMat.Add(leftmostPts[1]);
随时随地看视频慕课网APP

相关分类

Python
我要回答