How to set focus at some object in CameraEx?

HappyDad

Member
Licensed User
Longtime User
I am using CameraEx, and already added code to support focus mode according to :
http://www.b4x.com/forum/additional...amera-library-functionality-5.html#post141421

So, how can I set focus to some object in the scene?
I guess I should use "fixed" focus mode?
If so, how do I let the camera know which object it should focus on?
I can use Touch event of a panel and get where the user touched.
Afther that, how to let the camera know that it should focus on that position in the scene?

Thanks!
 

HappyDad

Member
Licensed User
Longtime User
Hi,

I tried to add setFocusAreas method to CameraEx class,
but I am getting "Camera$Area can not cast on CameraArea" error.
I have no java programming knowledge at all, so please help me checking where the problem is.

In CameraEx Class, I added:

B4X:
Sub Class_Globals
   '.....
          Type CameraArea (therect As Rect, weight As Int )
End Sub
and

B4X:
Public Sub SetFocusAreas(areas As List )
   Dim strs(1) As String 
   Dim lists(1) As Object 
   lists(0)=areas
   strs(0)="java.util.List"
   r.target = parameters    
   r.RunMethod4("setFocusAreas", lists, strs)   
   
End Sub
I checked using "getMaxNumFocusAreas" and found there is only one focus area supported, so in the above sub, I only use arrays with upper bound 1.

In the main code, I tried to call this method and got the above error:

B4X:
Sub Button1_Click
   Dim aaa As List 
   aaa.Initialize 
   Dim bbb As Rect 
   bbb.Initialize (-100,-100,100,100)
   Dim ccc As Int
   ccc=1000
   Dim ddd As CameraArea 
   ddd.Initialize 
   ddd.therect  =bbb
   ddd.weight =ccc
   aaa.Add (ddd)
   camEx.SetFocusAreas (aaa)
   
End Sub
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
setFocusAreas wants a specific Java type android.hardware.Camera$Area , you cannot just use your own type. You need to fill your list with the correct type which you can generate with Reflection.CreateObject2. Sorry, too busy to give an example as I'm off to get out the tractor mower to cut the field while the weather holds. If you can't crack it post again and I'll knock together an example later or tomorrow if no-one else gets in first.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
The bloody tractor had a puncture when I went to start it :( and as the tyres are tubeless there's nothing I can do to fix it at home. :mad: So I put this together. If you want more than one area it should be easy to add more. It compiles and runs without error but I don't know for sure if it actually does anything!
B4X:
Public Sub SetFocusArea(area As Rect, weight As Int )
   Dim r1, r2 As Reflector
   Dim params() As Object
   Dim types() As String
   params = Array As Object(area, weight)
   types = Array As String("android.graphics.Rect", "java.lang.int")   
   r1.Target = r1.CreateObject2("android.hardware.Camera$Area", params, types)
   Msgbox(r1.TypeName,"")
   
   Dim list1 As List
   list1.Initialize
   list1.Add(r1.Target)
   r2.target = camEx.parameters    
   r2.RunMethod4("setFocusAreas", Array As Object(list1), Array As String("java.util.List"))   
   
   camEx.CommitParameters 
End Sub
 
Upvote 0

HappyDad

Member
Licensed User
Longtime User
Sorry to hear about your tractor, I hope it gets fixed soon.

Your code runs without problem.
But seems it doesn't do anything to set the focus.
No matter how I touch and set different region of the the picture to focus,
the focused part of the picture doesn't change.

When the program starts to run,
I use "SetContinuousAutoFocus " in "Camera_Ready" sub.
After removing that line,
the camera seems no longer do auto focus.
Looks like I need to call "autoFocus" after each time I set the focus area?
Camera | Android Developers)
And looks like I need to create an call back object, like this?

B4X:
   Dim r1 As Reflector 
   r1.Target =r1.CreateObject ("android.hardware.Camera.AutoFocusCallback")
The call back should be a sub to call when the autoFocus success?
How do I specify the sub to the callback?
And what if the autoFocus fails?
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
Like a lot of the Android documentation the Camera class is devoid of any real explanation of how to use it! I doubt that setting a callback is necessary for it to work, I would have thought it existed for notification purposes. Camera.AutoFocusCallback is an Interface and needs to be implemented by a concrete class which you can't do by reflection.

You could try passing null to autoFocus. If an autofocus was in operation when TakePicture is called I would expect it be allowed to complete before taking the picture but in practice who knows! You could try a time delay.
 
Upvote 0

aeropic

Active Member
Licensed User
Longtime User
Hi all,

Playing around with CameraEx class, I've added Agraham's piece of code for setFocusArea and updated the main activity in order to use the Panel1_touch event :

B4X:
Sub Panel1_Touch (Action As Int, X As Float, Y As Float)
   
        Dim rect1 As Rect
       
        Dim myleft As Int
        Dim mytop As Int
        myleft = (X/Panel1.width)* 2000 -1000
        mytop = (Y/Panel1.Height)*2000 - 1000
       
        If Action = 1 Then
       
            ToastMessageShow(Action & " x : " & myleft & " Y : " & mytop, False)
            rect1.Initialize(myleft,mytop,myleft + 210 , mytop + 210)

            camEx.cancelAutoFocus
            camEx.setFocusMode("macro")
            camEx.SetFocusArea(rect1, 1000 )
          camEx.FocusAndTakePicture
       
        End If
       
End Sub

It seems to work (at least the correct touch event is triggered) but there is no effect of the set focus area : the camera still focuses in the center area

As I don't know how is coded the camera lib cam.AutoFocus sub, I'm a bit stalled !!!!

Any help would be appreciated.
Thanks
Alain
 

Attachments

  • CameraEx3.zip
    201.8 KB · Views: 503
Upvote 0

aeropic

Active Member
Licensed User
Longtime User
Are you sure that you need to call cam.AutoFocus?

Note that this line is wrong:
B4X:
rect1.Initialize(myleft,mytop,myleft + 210 , mytop + 210)

It should be 210dip.

Thanks Erel for the 210bpi , I will fix it.

For the autofocus, my understanding of the camera behavior is :
camEx.SetFocusArea(rect1, 1000 ) <<<<< this only moves the area in which the focus will be be done according to the last parameter weighting
camEx.FocusAndTakePicture <<<<<< this line is here to ask for a focus and then, wait for the focus done event


In fact, maybe the last line is not the correct one to ask for a focus ? I understood from there ( http://stackoverflow.com/questions/18460647/android-setfocusarea-and-auto-focus) that I had to go through an autofocus order but it does not seem to work !

They finish with a "autofocus(this)". I suppose the B4A cam.autofocus sub is equvalent to the AutoFocus(this) ?

Moreover, if I remove the autofocus at the end the lens does not focus at all ...


the android doumentation only states this : "Focus area only has effect if the current focus mode is
FOCUS_MODE_AUTO, FOCUS_MODE_MACRO,
FOCUS_MODE_CONTINUOUS_VIDEO, or
FOCUS_MODE_CONTINUOUS_PICTURE."


I must admit i'm a bit lost. But I think it would be really nice to make it work, this would be a must for CameraEX class, wouldn't it ?
 
Upvote 0

aeropic

Active Member
Licensed User
Longtime User
Hi all,

I try to spend more time on the focusareas matter !
I made some progress using in cameraEX class this code + Agraham setfocusAreas one:

B4X:
'public List<Camera.Area> getFocusAreas ()
'Gets the current focus areas. Camera driver uses the areas to decide focus.
Public Sub GetFocusAreas As List
    r.target = parameters
    Return r.RunMethod("getFocusAreas")
End Sub

and in the main this subroutine :
B4X:
Sub Panel1_Touch (Action As Int, X As Float, Y As Float)
  
        Dim rect1 As Rect
        Dim myleft As Int
        Dim mytop As Int
        myleft = (X/Panel1.width)* 2000 -1000
        mytop = (Y/Panel1.Height)*2000 - 1000
      
        If Action = 1 Then
            ToastMessageShow(Action & " x : " & myleft & " Y : " & mytop, False)
            rect1.Initialize(myleft,mytop,myleft + 210dip , mytop + 210dip)

camEx.SetContinuousAutoFocus   '<====================== ADDED THIS SEEMS TO IMPROVE THE BEHAVIOR !
  
    Dim focusAreasList As List = camEx.GetFocusAreas
    If focusAreasList.IsInitialized = False Then
        Log(TAB & "focus areas Not supported.")
    Else
        Dim focus As String
        For i=0 To focusAreasList.Size-1
            Log(focusAreasList.Get(i) )
            Log(TAB & i)
        Next
    End If

            camEx.SetFocusArea(rect1, 1000 )
          camEx.FocusAndTakePicture
      
        End If
End Sub

when pressing the screen I get a first log where focusAreasList is not initialized. But when pressing a second time I get this log:
B4X:
Continuous-picture    <===== log added in CamEx.setcontinuousAutoFocus
  focus areas Not supported. <=== first log fails
AutoFocus error.
Continuous-picture
android.hardware.Camera$Area@42883490 <== second log is successfull !
  0  <=== focusareaslist.size = 1
AutoFocus error.

Now I'm somewhat stalled because of my Java skills which are close to NULL :(

Who could help me to put the result of GetFocusAreas (the Camera$Area object) into B4A variables one rect and one int .... ?

thanks in advance...
 
Upvote 0

aeropic

Active Member
Licensed User
Longtime User
I'm glad to have the manual focus working :)

the right code (at least for my S3) is:
B4X:
Sub Panel1_Touch (Action As Int, X As Float, Y As Float) As Boolean
        Dim rect1 As Rect
        Dim myleft As Int
        Dim mytop As Int
        myleft = (X/Panel1.width)* 2000 -1000
        mytop = (Y/Panel1.Height)*2000 - 1000
        Log ("x=" & X & " Y=" & Y)
        If Action = Activity.ACTION_UP Then
        
            Log("focusarea: " & Action & " x : " & myleft & " Y : " & mytop)
            rect1.Initialize(myleft,mytop,myleft + 200 , mytop + 200)

            camEx.SetFocusArea(rect1, 1000 )
            camEx.setFocusMode("auto")
            camEx.commitparameters            '<========= THIS WAS THE PROBLEM
            Dim focusAreasList As List = camEx.GetFocusAreas
    If focusAreasList.IsInitialized = False Then
        Log(TAB & "focus areas Not supported.")
    Else
        Dim focus As String
        For i=0 To focusAreasList.Size-1
            Log(focusAreasList.Get(i) )
            Log(TAB & i)
        Next
    End If
           
          camEx.FocusAndTakePicture
       
        End If
        Return True

End Sub

The code of course needs some cleaning:
- checks that the rectangle is not outside the +/-1000 limits
- check that the camera supports all the functions...

question to EREL : some posts ago, Erel, you adviced me to write this line with "dips" rect1.Initialize(myleft,mytop,myleft + 200dips , mytop + 200dips)...
In fact I'm not sure you're right as those focus areas rectangles do not refer to the screen coordinates but to another system top left = -1000 -1000 bottom right = 1000 1000 whatever the screen resolution or density.
Am I right or do I miss something ?

Even if I'm no more stalled, I remain interested in the answer to the other question :
Who could help me to put the result of GetFocusAreas (the Camera$Area object) into B4A variables one rect and one int .... ?

Enjoy B4A ;)
 
Upvote 0

aeropic

Active Member
Licensed User
Longtime User
If the coordinates are not related to the device scale then you should not use dips.
OK this was my understanding as the API documentation states that :
"Each focus area is a rectangle with specified weight. The coordinates of the rectangle range from -1000 to 1000. (-1000, -1000) is the upper left point. (1000, 1000) is the lower right point."

Many thanks for the GetFocusAreas code, I have tested it. It works fine and I must admit, I would never have found this alone !
 
Last edited:
Upvote 0

Semen Matusovskiy

Well-Known Member
Licensed User
Does anyone have a working example of SetFocusAreas ? I tried expected sequence (CancelAutoFocus; SetFocusAreas + setMeteringAreas;
SetFocusMode("auto"); Commitparameters; AutoFocus). But this doesn't work on my phones (Android 7 and 8). Autofocus "eats" focus areas and makes ordinary autofocus. Any help ?
 
Upvote 0
Top