C# WPF,根据虚拟屏幕分辨率查找坐标

问题描述 投票:0回答:1

我正在使用 kinect SDK 和 OpenCV 开发一个 wpf 项目, 我需要做的是创建一个框,跟随在 kinect 相机中显示的斑点,并检查该斑点是否位于通过选择 4 个点(矩形的角)添加的矩形内

MCvBox2D box = contours.GetMinAreaRect();
openCVImg.Draw(box, new Bgr(System.Drawing.Color.Red), 2);

POINT p = new POINT { x = (int)box.center.X, y = (int)box.center.Y };

double minX = Math.Min(Canvas.GetLeft(dot1), Math.Min(Canvas.GetLeft(dot2), Math.Min(Canvas.GetLeft(dot3), Canvas.GetLeft(dot4))));
double minY = Math.Min(Canvas.GetTop(dot1), Math.Min(Canvas.GetTop(dot2), Math.Min(Canvas.GetTop(dot3), Canvas.GetTop(dot4))));
double maxX = Math.Max(Canvas.GetLeft(dot1), Math.Max(Canvas.GetLeft(dot2), Math.Max(Canvas.GetLeft(dot3), Canvas.GetLeft(dot4))));
double maxY = Math.Max(Canvas.GetTop(dot1), Math.Max(Canvas.GetTop(dot2), Math.Max(Canvas.GetTop(dot3), Canvas.GetTop(dot4))));
if (p.x >= minX && p.x <= maxX && p.y >= minY && p.y <= maxY)
{
...
}

盒子是围绕斑点创建的,点1,..,点4是矩形的角,点p是盒子的中心。 if 语句检查是否在矩形内找到了框

问题是当我检查 Dots 的坐标时,它们显示的坐标与点 p 不同。 例如当 box.X 超过 minX 时,它显示 box.X = 125 的坐标和 maxX=634 的坐标。

我非常乐意了解我在这里做错了什么以及如何解决它。

谢谢

c# wpf opencv kinect-sdk kinect-v2
1个回答
0
投票

您可以使用

Visual.PointFromScreen
将以屏幕坐标表示的点转换为
Visual
的坐标系(在您的情况下为托管
Canvas
元素)。

您还应该避免混合

System.Drawing
System.Windows
命名空间。因为这是一个 WPF 应用程序,您应该立即将从 OpenCV API 返回的所有
System.Drawing
类型转换为
System.Windows
类型。

您可以通过使用

Rect.Contains
来测试
Point
是否包含在
Rect
定义的矩形内,进一步改进代码。处理
Rect
而不是“松散”坐标点至少可以提高代码的可读性。

private void HandleTrackingBox(Contour<PointF> contour)
{
  MCvBox2D box = contour.GetMinAreaRect();
  openCVImg.Draw(box, new Bgr(System.Drawing.Color.Red), 2);
  var testPointFromScreen = new System.Windows.Point(box.center.X, box.center.Y);

  System.Windows.Rect referenceBounds = CreateReferenceBounds();
  bool isTestPointValid = IsScreenTestPointWithinBounds(referenceBounds, testPointFromScreen);
  if (isTestPointValid)
  {
    // TODO::Handle test point is within the bounds
  }
}

private System.Windows.Rect CreateReferenceBounds()
{
  double minX = Math.Min(Canvas.GetLeft(dot1), Math.Min(Canvas.GetLeft(dot2), Math.Min(Canvas.GetLeft(dot3), Canvas.GetLeft(dot4))));
  double minY = Math.Min(Canvas.GetTop(dot1), Math.Min(Canvas.GetTop(dot2), Math.Min(Canvas.GetTop(dot3), Canvas.GetTop(dot4))));
  double maxX = Math.Max(Canvas.GetLeft(dot1), Math.Max(Canvas.GetLeft(dot2), Math.Max(Canvas.GetLeft(dot3), Canvas.GetLeft(dot4))));
  double maxY = Math.Max(Canvas.GetTop(dot1), Math.Max(Canvas.GetTop(dot2), Math.Max(Canvas.GetTop(dot3), Canvas.GetTop(dot4))));

  double boundsWidth = maxX - minX;
  double boundsHeight = maxY - minY;
  var boundsSize = new System.Windows.Size(boundsWidth, boundsHeight);
  var boundsLocation = new System.Windows.Point(minX, minY);
  var referenceBounds = new System.Windows.Rect(boundsLocation, boundsSize);

  return referenceBounds;
}

private bool IsScreenTestPointWithinBounds(Rect referenceBounds, System.Windows.Point screenTestPoint)
{
  // Use the hosting Canvas to transform the screen point 
  // to a point relative to the Canvas element
  var relativeTestPoint = this.HostingCanvas.PointFromScreen(testPointFromScreen);
  return referenceBounds.Contains(relativeTestPoint);
}

© www.soinside.com 2019 - 2024. All rights reserved.