Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/212.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# 摄像机对焦时如何实现视觉指示_C#_Android_Xamarin_Xamarin.android_Android Camera - Fatal编程技术网

C# 摄像机对焦时如何实现视觉指示

C# 摄像机对焦时如何实现视觉指示,c#,android,xamarin,xamarin.android,android-camera,C#,Android,Xamarin,Xamarin.android,Android Camera,当用户在我的应用程序中手动对焦(点击对焦)相机页面时,我想显示一个基本圆 我已经在下面的点击中实现了自动对焦,但我不确定如何在对焦时绘制圆,并在视图未对焦时将其关闭,以及在相机对焦时继续重新绘制圆。指示器不应该是最终照片的一部分,只是在相机对焦或不对焦时为用户提供指导 以下是我目前掌握的情况: public class AutoFocusCallback : Java.Lang.Object, IAutoFocusCallback { public void OnAutoFocus(bo

当用户在我的应用程序中手动对焦(点击对焦)相机页面时,我想显示一个基本圆

我已经在下面的点击中实现了自动对焦,但我不确定如何在对焦时绘制圆,并在视图未对焦时将其关闭,以及在相机对焦时继续重新绘制圆。指示器不应该是最终照片的一部分,只是在相机对焦或不对焦时为用户提供指导

以下是我目前掌握的情况:

public class AutoFocusCallback : Java.Lang.Object, IAutoFocusCallback
{
    public void OnAutoFocus(bool success, Android.Hardware.Camera camera)
    {
        var parameters = camera.GetParameters();
        var supportedFocusModes = parameters.SupportedFocusModes;

        if (string.IsNullOrEmpty(parameters.FocusMode))
        {
            string focusModeContinuous = Android.Hardware.Camera.Parameters.FocusModeContinuousPicture;
            string focusModeAuto = Android.Hardware.Camera.Parameters.FocusModeAuto;

            if (supportedFocusModes != null && supportedFocusModes.Any())
            {
                if (supportedFocusModes.Contains(focusModeContinuous))
                {
                    parameters.FocusMode = focusModeContinuous;
                }
                else if (supportedFocusModes.Contains(focusModeAuto))
                {
                    parameters.FocusMode = focusModeAuto;
                }
            }
        }

        if (supportedFocusModes != null && supportedFocusModes.Any())
        {
            if (parameters.MaxNumFocusAreas > 0)
            {
                parameters.FocusAreas = null; 
            }

             if (success)
             {
                CameraPage cameraPage = new CameraPage();
                Canvas canvas = new Canvas(); 
                cameraPage.Draw(canvas); 
            }
            camera.SetParameters(parameters);
            camera.StartPreview();
        }
    }
}

public bool OnTouch(Android.Views.View v, MotionEvent e)
{
    if (camera != null)
    {
        var parameters = camera.GetParameters();
        camera.CancelAutoFocus();
        Rect focusRect = CalculateTapArea(e.GetX(), e.GetY(), 1f);

        if (parameters.FocusMode != Android.Hardware.Camera.Parameters.FocusModeAuto)
        {
            parameters.FocusMode = Android.Hardware.Camera.Parameters.FocusModeAuto;
        }
        if (parameters.MaxNumFocusAreas > 0)
        {
            List<Area> mylist = new List<Area>();
            mylist.Add(new Android.Hardware.Camera.Area(focusRect, 1000));
            parameters.FocusAreas = mylist;
        }

        try
        {
            camera.CancelAutoFocus();
            camera.SetParameters(parameters);
            camera.StartPreview();
            camera.AutoFocus(new AutoFocusCallback());
        }
        catch (System.Exception ex)
        {
            Console.WriteLine(ex.ToString());
            Console.Write(ex.StackTrace);
        }
        return true;
    }
    else
    {
        return false;
    } 
}

private Rect CalculateTapArea(object x, object y, float coefficient)
{
    var focusAreaSize = Math.Max(textureView.Width, textureView.Height) / 8; //Recommended focus area size from the manufacture is 1/8 of the image
    int areaSize = focusAreaSize * (int)coefficient;

    int left = clamp(Convert.ToInt32(x) - areaSize / 2, 0, textureView.Width - areaSize);
    int top = clamp(Convert.ToInt32(y) - areaSize / 2, 0, textureView.Height - areaSize);

    RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
    Matrix.MapRect(rectF);

    return new Rect((int)System.Math.Round(rectF.Left), (int)System.Math.Round(rectF.Top), (int)System.Math.Round(rectF.Right), (int)System.Math.Round(rectF.Bottom));
}

private int clamp(int x, int min, int max)
{
    if (x > max)
    {
        return max;
    }
    if (x < min)
    {
        return min;
    }
    return x;
}

public override void Draw(Canvas canvas)
{
    base.Draw(canvas);
    Paint p = new Paint();
    p.Color = Android.Graphics.Color.White; 
    p.SetStyle(Paint.Style.Stroke);
    p.StrokeWidth = 3; 
    canvas.DrawCircle(300, 300, 100, p);
}
公共类AutoFocusCallback:Java.Lang.Object,IAutoFocusCallback
{
自动对焦上的公共空白(bool success,Android.Hardware.Camera)
{
var参数=camera.GetParameters();
var supportedFocusModes=参数。supportedFocusModes;
if(string.IsNullOrEmpty(parameters.FocusMode))
{
字符串focusModeContinuous=Android.Hardware.Camera.Parameters.FocusModeContinuousPicture;
字符串focusModeAuto=Android.Hardware.Camera.Parameters.focusModeAuto;
if(supportedFocusModes!=null&&supportedFocusModes.Any())
{
if(supportedFocusModes.Contains(focusModeContinuous))
{
parameters.FocusMode=focusModeContinuous;
}
else if(supportedFocusModes.Contains(focusModeAuto))
{
parameters.FocusMode=focusModeAuto;
}
}
}
if(supportedFocusModes!=null&&supportedFocusModes.Any())
{
如果(parameters.MaxNumFocusAreas>0)
{
parameters.focusreas=null;
}
如果(成功)
{
CameraPage CameraPage=新的CameraPage();
画布=新画布();
cameraPage.Draw(画布);
}
设置参数(参数);
camera.StartPreview();
}
}
}
公共bool OnTouch(Android.Views.View v,MotionEvent e)
{
如果(照相机!=null)
{
var参数=camera.GetParameters();
camera.CancelAutoFocus();
Rect focusRect=calculateparea(e.GetX(),e.GetY(),1f);
if(parameters.FocusMode!=Android.Hardware.Camera.parameters.FocusModeAuto)
{
parameters.FocusMode=Android.Hardware.Camera.parameters.FocusModeAuto;
}
如果(parameters.MaxNumFocusAreas>0)
{
名单

这是我的Xamarin.Forms Android应用程序

编辑:这里有一份相机的Android源代码副本,但不确定他们在哪里制作指示器:

没有官方答案的类似SO帖子:

正如你所看到的,很多人都有相同的问题,但没有答案!如果我还不清楚,请告诉我

我已经在下面的点击中实现了自动对焦,但我不确定如何在对焦时绘制圆,并在视图未对焦时将其关闭,以及在相机对焦时继续重新绘制圆

您发布的图片在我看来像是一个系统摄像头,如果使用
Intent
启动系统摄像头,我不确定是否可以在系统的摄像头视图上添加一个聚焦圈。但我猜您可能使用了
SurfaceView
TextureView
来自己主持摄像头

如果是这样,对于您的场景,我认为最简单的方法是在布局中放置一个
ImageView
,并根据相机焦点状态更改其可见性并重置其
LayoutParameters
。例如,图像源必须是透明的。然后我的布局如下所示:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  <TextureView android:id="@+id/textureView"
               android:layout_height="match_parent"
               android:layout_width="match_parent" />

  <Button android:id="@+id/take_photo"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:text="@string/takephoto" />

  <ImageView android:id="@+id/focuscircle"
             android:layout_height="80dp"
             android:layout_width="80dp"
             android:layout_centerInParent="true"
             android:src="@drawable/FocusCircle"
             android:visibility="invisible" />
</RelativeLayout>
要使其消失,您可以在
AutoFocusCallBack
中的
success
状态下进行如下编码:

if (success)
{
    Task.Delay(1000);
    Activity1._focusimg.Visibility = ViewStates.Invisible;
}
为了使
ImageView
可以从
AutoFocusCallBack
访问,您可以在xamarin中将其设置为静态视图:

private Android.Hardware.Camera _camera;
private TextureView _textureView;

public static ImageView _focusimg;

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
    SetContentView(Resource.Layout.Main);

    _textureView = (TextureView)this.FindViewById(Resource.Id.textureView);
    _textureView.SurfaceTextureListener = this;
    _textureView.Touch += _textureView_Touch;

    var tpBtn = (Button)this.FindViewById(Resource.Id.take_photo);
    tpBtn.Click += TpBtn_Click;

    _focusimg = (ImageView)this.FindViewById(Resource.Id.focuscircle);
}
每次成功设置焦点时,它都可以正常工作,但我发现有时当我点击
TextureView
时,它不会触发
\u TextureView\u Touch
事件,我没有深入研究这个问题


另一种方法是在
画布上动态画一个圆圈,就像你在代码中所做的那样,它也很有效,但我发现使用这种方法我的演示响应很慢,我也没有深入挖掘这个问题。无论如何,我认为第一种使用图像的方法更简单,如果需要演示,请留下评论。

有人能告诉我是什么吗y我不清楚?我正在进一步编辑这个,但我觉得我很清楚。我甚至还添加了一张我想画的视觉指示器的照片。我认为这是一个可以接受的问题,所以人们可以是鸡巴。在我看来,这也很好,非常有效。伟大的人都有同感!我昨天做了和你一样的事情来解决这个问题。我可以分享我的解决方案(尽管可能不如你的准确)。我希望得到反馈。我稍后会分享:)Grace,这部分:“有时当我点击TextureView时,它不会触发_TextureView_Touch事件,我没有深入挖掘这个问题”。你知道为什么会这样吗?@Euridice01,不知道,如果我们将
Image
设置为
ViewStates。不可见的
,它仍然会占用空间,也许我点击了图像…也许我们可以试着将其更改为
ViewStates。消失了。
private Android.Hardware.Camera _camera;
private TextureView _textureView;

public static ImageView _focusimg;

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
    SetContentView(Resource.Layout.Main);

    _textureView = (TextureView)this.FindViewById(Resource.Id.textureView);
    _textureView.SurfaceTextureListener = this;
    _textureView.Touch += _textureView_Touch;

    var tpBtn = (Button)this.FindViewById(Resource.Id.take_photo);
    tpBtn.Click += TpBtn_Click;

    _focusimg = (ImageView)this.FindViewById(Resource.Id.focuscircle);
}