Android Question Measuring image brightness in real time

Falcon1208

Member
Licensed User
I would like to measure image brightness and measuring several points in real time, like kkingstoun said long ago, is my idea too. I need to do that 30 times per second and just store color values in an array so I thing using ameraEx.PreviewImageToJpeg and testing pixels in the .jpeg image will be too slow.

Is there a way to directly use the data() array passed in the preview event ?

This array use a special, but known, format. Is there a way to extract directly
some points color from this array without converting in jpeg format before ?
 

MaFu

Well-Known Member
Licensed User
Longtime User
If you don't need it immediately:
The upcoming version 2 of my MFLib contains a YUV2Bitmap function in native C.
Here's an example app demonstrating the function.
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
If you just want brightness, the first bytes of the data[] structure (which is YUV) is the Y (=lightness) . So, sampling these values at some selected pixel positions (array positions) can give you a good measurement of the image brightness
 
Upvote 0

Falcon1208

Member
Licensed User
If you just want brightness, the first bytes of the data[] structure (which is YUV) is the Y (=lightness) . So, sampling these values at some selected pixel positions (array positions) can give you a good measurement of the image brightness

Nice ! So, If I understand correctly, as Data() seem to be a vector colors data are organised like that :

Point1 point2 ....
Y U V Y U V ... (colors values)
0 1 2 3 4 5 ... (Data() index)

Right ?

I would like to sample points that are localized near the center of the image.
Do you know how points are organized in Data() vector ? What is the
relation between x,y images point's coordinates and their (their index) position in data() ?
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
Nice ! So, If I understand correctly, as Data() seem to be a vector colors data are organised like that :

Point1 point2 ....
Y U V Y U V ... (colors values)
0 1 2 3 4 5 ... (Data() index)

Right ?

I would like to sample points that are localized near the center of the image.
Do you know how points are organized in Data() vector ? What is the
relation between x,y images point's coordinates and their (their index) position in data() ?

Here
 
Upvote 0

Falcon1208

Member
Licensed User

Ok thanck you.

But whatever I do I can't increase my FPS (near 10 frames/second).
I tried camEx.SetPreviewFpsRange(1000,1000) after having update
CameraExClass.bas with this sub and saw min and max values
(1000 - 30000 with my phone) using :

'Dim MinMax(2) As Int
'camEx.GetPreviewFpsRange(MinMax)
'Log($"Min = ${MinMax(0)}"$)
'Log($"Max = ${MinMax(1)}"$)

Without success. I also tried to change picture size, it hasn't
have any effect too, FPS is always 10, as if it would have been
set to this value somewhere in android 5 ...

Any idea ?

(my file in joined piece)
 

Attachments

  • CameraExClass.bas
    9.1 KB · Views: 246
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
My two cents:

  • The SetPreviewFpsRange() will only accept values that are in the list returned by GetSupportedPreviewFpsRange(). So, as MaFu says, perhaps the device only has one range (1000,30000) and does not allow the user to change it. Which means that it will do what it wants depending on some condition
  • Also, if it allows more than one option, after changing the required frame rate (using one of the allowed ranges), you should always call CommitParameters() after it

However, it seems to be that there is one trick to tell the device that you are using the preview for some special purpose, and it will do "its best" to give the 30fps
. Look HERE. So, according to that, you can, after SetPReviewFpsRange and before CommitParameters, to call "SetRecordingHint". It can be achieved through reflection (not tested, but you can try) Add this to your CameraEx.bas

B4X:
Public Sub SetRecordingHint
  r.target = parameters
  r.RunMethod2("setRecordingHint", True, "java.lang.boolean")
End Sub
 
Upvote 0

Falcon1208

Member
Licensed User
Thanck you. FPS rate drop to 18 +/- 4

Nevertheless it is not the one I tuned with
camEx.SetPreviewFpsRange() whatever value I use.

Image size or jpeg quality doesn't change FPS too.

The only thing that has change (increase) this FPS is
camEx.SetRecordingHint.

I is so true that this simple code :

B4X:
camEx.SetRecordingHint
camEx.CommitParameters
camEx.StartPreview

does the job. Nothing else has any impact
on this FPS rate that is still a little low and
highly variable.

Is there a way to force preview at choosen
time (not taking a picture) ?
 
Upvote 0

Falcon1208

Member
Licensed User
Thanck you. FPS rate drop to 18 +/- 4

Nevertheless it is not the one I tuned with
camEx.SetPreviewFpsRange() whatever value I use.

Image size or jpeg quality doesn't change FPS too.

The only thing that has change (increase) this FPS is
camEx.SetRecordingHint.

I is so true that this simple code :

B4X:
camEx.SetRecordingHint
camEx.CommitParameters
camEx.StartPreview

does the job. Nothing else has any impact
on this FPS rate that is still a little low and
highly variable.

Is there a way to force preview at choosen
time (not taking a picture) ?
Thanck you. FPS rate drop to 18 +/- 4

Nevertheless it is not the one I tuned with
camEx.SetPreviewFpsRange() whatever value I use.

Image size or jpeg quality doesn't change FPS too.

The only thing that has change (increase) this FPS is
camEx.SetRecordingHint.

I is so true that this simple code :

B4X:
camEx.SetRecordingHint
camEx.CommitParameters
camEx.StartPreview

does the job. Nothing else has any impact
on this FPS rate that is still a little low and
highly variable.

Is there a way to force preview at choosen
time (not taking a picture) ?


Just after having post my last message I tried an other thing :
Decreasing Panel1 size. It works, setting Panel1 to 10%x x 10%y
induce a FPS of 23 +/- 2.

So it seems that the system spend many time to display/resize
the image. Is there a way to avoid displaying the image ?

I don't need to show what the camera see, I only need to
estimate image brightness.
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
You could make the panel smaller and place it behind a button or place it in negative coordinates.

Also, as a try, you could configure some parameters, such as wihte balance, not to be auto, since it means more work for the camera.
 
Upvote 0
Top