我正在使用 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 的坐标。
我非常乐意了解我在这里做错了什么以及如何解决它。
谢谢
您可以使用
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);
}