Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在xamarin窗体图像视图上定位地标?_C#_Image_Xamarin.forms - Fatal编程技术网

C# 如何在xamarin窗体图像视图上定位地标?

C# 如何在xamarin窗体图像视图上定位地标?,c#,image,xamarin.forms,C#,Image,Xamarin.forms,我正在使用一个人脸检测服务,给我一张图片,它会返回我的人脸标志位置。我的目标是在屏幕上显示的图片上定位这些地标 我的想法是使用带有图像视图的AbosluteLayout,并将地标定位在图片上。重叠效果很好。问题是地标的点指的是原始图片大小坐标,渲染图像的大小完全不同。目前我使用的是AspectFit,所以全图显示在AbsoluteLayout中,保留纵横比,通常使用字母框 我尝试的是考虑屏幕密度,并将其应用于原始地标点,如下所示: rightEyePoint.X=转换为32(rightEyePo

我正在使用一个人脸检测服务,给我一张图片,它会返回我的人脸标志位置。我的目标是在屏幕上显示的图片上定位这些地标

我的想法是使用带有图像视图的AbosluteLayout,并将地标定位在图片上。重叠效果很好。问题是地标的点指的是原始图片大小坐标,渲染图像的大小完全不同。目前我使用的是AspectFit,所以全图显示在AbsoluteLayout中,保留纵横比,通常使用字母框

我尝试的是考虑屏幕密度,并将其应用于原始地标点,如下所示:

rightEyePoint.X=转换为32(rightEyePoint.X/displayDensity)

它变得更近了,但不是在所有的图片上(不同于风景画/肖像画)

然后我想,考虑到原始图像,我可能想知道渲染图像的比例因子,这样我可以变换所有的地标点,但我不知道怎么做。我尝试创建一个自定义图像视图和渲染器,以尝试从中获取比例计算,但没有成功,因为我没有干涉本机图像组件的计算位置:

public class CustomImageView : Image
{
    protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
    {
        return base.OnMeasure(widthConstraint, heightConstraint);


    }

    protected override void OnSizeAllocated(double width, double height)
    {
        base.OnSizeAllocated(width, height);

    }

    protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        base.OnPropertyChanged(propertyName);
    }
}

public class CustomImageViewRenderer : ImageRenderer
{
    public CustomImageViewRenderer(Context context) : base(context) { }

    protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
    {
        base.OnElementChanged(e);
        if(e.NewElement != null)
        {
            var image = Control as ImageView;

        }
    }
    protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
    {
        base.OnSizeChanged(w, h, oldw, oldh);
    }

    protected override Task TryUpdateBitmap(Image previous = null)
    {
        return base.TryUpdateBitmap(previous);
    }
}
公共类CustomImageView:图像
{
测量时受保护的覆盖大小请求(双宽度约束、双高度约束)
{
返回base.OnMeasure(宽度约束、高度约束);
}
IzealLocated上的受保护覆盖空心(双倍宽度,双倍高度)
{
底座。尺寸定位(宽度、高度);
}
受保护的重写无效OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
base.OnPropertyChanged(propertyName);
}
}
公共类CustomImageViewRenderer:ImageRenderer
{
公共CustomImageViewRenderer(上下文):基本(上下文){}
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
基础。一个要素发生变化(e);
if(例如NewElement!=null)
{
var image=控件作为ImageView;
}
}
IzeChanged上的受保护覆盖无效(int w、int h、int oldw、int oldh)
{
基部。沿Z方向变化(w,h,oldw,oldh);
}
受保护的覆盖任务TryUpdateBitmap(Image-previous=null)
{
返回base.TryUpdateBitmap(上一个);
}
}
然后我想我可以自己计算当前渲染图像的大小,但我似乎无法得到它。所以我只得到了xamarin表单图像组件的大小,但没有得到其中渲染的图像。在这一点上,我认为我可以根据纵横比计算渲染图像的大小,因为我使用的是AspectFit,但在这个过程中遇到了问题

axml(示例):

非常感谢

一些数学知识

Xamarin Forms使用与设备无关的像素,所以我猜您需要的是图像在帧内渲染的比率。假设它的A1:A2,其中一个单位x长。您的帧的比率是给定的,比如说B1:B2,其中一个单位是y长。我们的问题是x是未知的。所以我们需要把它从方程中取出来(字面意思是:D)

首先,您需要确定哪个更大,A1还是A2。为什么?因为较长的一侧将是完全适合框架的一侧。(例如,如果您的图像宽度大于高度,则在顶部和底部都会有信箱。如果您的图片高度大于宽度,则在左侧和右侧都会有信箱。)假设A2更大(意味着您图片的高度大于宽度)

在这种情况下,A2*x应等于B2*y。因此,x=B2/A2*y

你的图片将被放置在框架的中间,所以框架的另一面将是:

[{z}宽蓝色背景]-[image width]-[{z}宽蓝色背景]

现在我们只需要得到z的长度。这是(B1*y-(B2/A2*y)*A1)/2


现在,为了让数字更容易理解: 背景框大小:600 x 400(宽x高)-可从代码中检索-表示B1=3、B2=2和y=200

图像的比率:4:5-可以从原始图像大小中检索-意味着A1=4,A2=5,我们不知道x是什么。(因为这是你需要的一部分。)

这导致x=2/5*200=80

这最终意味着z是(3*200-80*4)/2=(600-320)/2=140

这意味着,在本例中,图像的第一次倾斜位于背景帧内的(140,0)位置


我希望这对你有所帮助,并让你创建自己的计算方法。

最后,我使用了一个更简单的系统。下面是我创建的用于获取渲染图像边界的方法的代码

private void CalculateRendredImageBounds()
    {
        Point origin = new Point();

        _renderedImageRatio = CurrentPhotoSize.Width / CurrentPhotoSize.Height;

        if (CurrentPhotoSize.Height > CurrentPhotoSize.Width)
        {
            //case height greater than width (portrait)
            _renderedPhotoWidth = (CurrentPhotoSize.Width * RenderedImageContainerSize.Height) / CurrentPhotoSize.Height;
            origin.X = Convert.ToInt32((RenderedImageContainerSize.Width - _renderedPhotoWidth) / 2);
            origin.Y = 0;

            _renderedImageBounds = new Rectangle(origin.X, origin.Y, _renderedPhotoWidth, RenderedImageContainerSize.Height);
        }
        else
        {
            //case width greater than height (landscape)
            _renderedPhotoHeight = (CurrentPhotoSize.Height * RenderedImageContainerSize.Width) / CurrentPhotoSize.Width;
            origin.X = 0;
            origin.Y = Convert.ToInt32((RenderedImageContainerSize.Height - _renderedPhotoHeight) / 2);

            _renderedImageBounds = new Rectangle(origin.X, origin.Y, RenderedImageContainerSize.Width, _renderedPhotoHeight);
        }
    }
然后,如果要在容器坐标系中查找点,可以使用以下命令

X景观:

Convert.ToInt32((originalXPos * RenderedImageContainerSize.Width) / CurrentPhotoSize.Width);
Convert.ToInt32((originalYPos * _renderedPhotoHeight) / CurrentPhotoSize.Height + (RenderedImageContainerSize.Height - _renderedPhotoHeight) / 2);
Y形景观:

Convert.ToInt32((originalXPos * RenderedImageContainerSize.Width) / CurrentPhotoSize.Width);
Convert.ToInt32((originalYPos * _renderedPhotoHeight) / CurrentPhotoSize.Height + (RenderedImageContainerSize.Height - _renderedPhotoHeight) / 2);
X肖像:

Convert.ToInt32((originalXPos * _renderedPhotoWidth) / CurrentPhotoSize.Width + (RenderedImageContainerSize.Width - _renderedPhotoWidth) / 2);
Convert.ToInt32((originalYPos * RenderedImageContainerSize.Height) / CurrentPhotoSize.Height);
Y肖像:

Convert.ToInt32((originalXPos * _renderedPhotoWidth) / CurrentPhotoSize.Width + (RenderedImageContainerSize.Width - _renderedPhotoWidth) / 2);
Convert.ToInt32((originalYPos * RenderedImageContainerSize.Height) / CurrentPhotoSize.Height);

注意:我没有显示私有属性声明,但我认为代码可读性足够。

您尝试过获取图像边界吗?是的,这是很容易知道的信息,但正如我在问题中所说的,您只会得到XamarinForms图像边界,而不会得到渲染图像框(可能有字母框)。感谢详细的响应,似乎这就是我要找的!我认为你用数字创建的例子是错误的,因为你使用的方程与肖像图像有关,但是你用的图像是横向的(600>400)。是吗?你是对的,我把那部分搞糟了,对不起:)我应该编辑吗,还是你能猜出来