我正在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而使用它),但是我假设我可以从中借鉴一些帮助方法。
到目前为止, This gist是我调整视角的主要指南,而for_point_warp
函数似乎提供了不错的指南。我只是不知道C#等效项。
答案 0 :(得分:1)
//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 step
Point tempPoint;
if(polyMatList[0].x > polyMatList[1].x)
{
tempPoint = polyMatList[0];
polyMatList[0] = polyMatList[1];
polyMatList[1] = tempPoint ;
}
// same goes for your bottom two points
if(polyMatList[2].x > polyMatList[3].x)
{
tempPoint = polyMatList[2];
polyMatList[2] = polyMatList[3];
polyMatList[3] = tempPoint ;
}
//now your list will be ordered tl, tr, bl, br
答案 1 :(得分:0)
这是我基于this tutorial实现的(尽管我确信我可以做些更优雅的事情)。
polyMat.convertTo(orientationMat, CvType.CV_32S); //conver MatOfPoint2f back to MatofPoint so it can be drawn
//sort by y val
polyMatList = 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 point
leftmostPts = 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);
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
orderedPolyMat.Add(rightmostPts[1]);
orderedPolyMat.Add(rightmostPts[0]);
} else {
orderedPolyMat.Add(rightmostPts[0]);
orderedPolyMat.Add(rightmostPts[1]);
}
orderedPolyMat.Add(leftmostPts[1]);