How to control iso manually in camera2, android - android

I am new in android and trying to figure out new camera2 effects. I have no idea how to control iso in camera preview manually.
Any help will be appreciated.
Thanks.

One way to determine if your device supports manual ISO control is to check if it supports the MANUAL_SENSOR capability.
If so, you can turn off auto-exposure by either disabling all automatics:
previewBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF);
or by just disabling auto-exposure, leaving auto-focus and auto-white-balance running:
previewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
Once you've disabled AE, you can manually control exposure time, sensitivity (ISO), and frame duration):
previewBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, exposureTime);
previewBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, sensitivity);
previewBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, frameDuration);
The valid ranges for these values can be found from SENSOR_INFO_EXPOSURE_TIME_RANGE and SENSOR_INFO_SENSITIVITY_RANGE for exposure and sensitivity. For frame duration, the maximum frame duration can be found from SENSOR_INFO_MAX_DURATION, and the minimum frame duration (max frame rate) depends on your session output configuration. See StreamConfigurationMap.getOutputMinFrameDuration for more details on this.
Note that once you disable AE, you have to control all 3 parameters (there are defaults if you never set one, but they won't vary automatically). You can copy the last-good values for these from the last CaptureResult before you turn off AE, to start with.

You have to set previewbuilder first like this:
mPreviewBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
and than
Range<Integer> range2 = characteristics.get(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE);
int max1 = range2.getUpper();//10000
int min1 = range2.getLower();//100
int iso = ((progress * (max1 - min1)) / 100 + min1);
mPreviewBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, iso);
progress is a variable for seekBar from onProgressChanged(SeekBar seekBar, int progress, boolean user) override method

Related

Adjustable but consistent/raw feed from Camera X (no AE or AWB)

*Note: I figured out why the image was too dark at max SENSOR_SENSITIVITY: it was just a matter of EXPOSURE_TIME being too short, had to pump it up to 8 digits. Now all I have to do is save the values for SENSOR_SENSITIVITY and EXPOSURE_TIME. So, this question is answered, unless there's a better way?
Using Camera X (Camera2Interop) I want to turn off auto-exposure and white balance. Because I want to manually adjust the brightness, and ideally have it locked at that value until I adjust it again.
I'm not capturing an image but just working with the preview, and image analysis.
When turning CONTROL_MODE off or AE off the preview & analysis are black (unless pointed directly at light bulb), and I can get an image by adjusting SENSOR_SENSITIVITY, but the image is still too dark at maximum and has noise in it. When I modify EXPOSURE_TIME the image goes 100% black no matter what.*
Using AE_LOCK + AE_EXPOSURE_COMPENSATION instead fixes the issue of the black preview and prevents auto-correction, but isn't consistent, for I don't have a way to reset the brightness to what was set previously. For example: if I open the main camera app and go back to mine the brightness is now locked at a different value.
Camera2Interop.Extender extender = new Camera2Interop.Extender(builder);
//extender.setCaptureRequestOption(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_OFF);
//extender.setCaptureRequestOption(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION,-1);
extender.setCaptureRequestOption(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_MACRO);
//extender.setCaptureRequestOption(CaptureRequest.SENSOR_EXPOSURE_TIME,10);
//extender.setCaptureRequestOption(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF);
//extender.setCaptureRequestOption(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
extender.setCaptureRequestOption(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_OFF);
//extender.setCaptureRequestOption(CaptureRequest.SENSOR_SENSITIVITY,99999);
extender.setCaptureRequestOption(CaptureRequest.CONTROL_AWB_LOCK,true);
extender.setCaptureRequestOption(CaptureRequest.CONTROL_AE_LOCK,true);
//extender.setCaptureRequestOption(CaptureRequest.BLACK_LEVEL_LOCK,true);
Another issue is When adjusting brightness via EXPOSURE_COMPENSATION it seems to compound. For example, if it's set to -3 the image gets a little darker with every start of the application, or probably every time startCameraX is run. Perhaps this is an easy fix by moving it out of startcamera, but I was attempting to start or reset to it's previously set value.
ExposureState exposureState = camera.getCameraInfo().getExposureState();
if (!exposureState.isExposureCompensationSupported()) return;
Range<Integer> range = exposureState.getExposureCompensationRange();
int index = exposureState.getExposureCompensationIndex();
if (range.contains(1) && index != -3) {
camera.getCameraControl().setExposureCompensationIndex(-3);
}
Also, all the warning that come along with the camera2 interop extender makes it seem odd that's the official solution.
Other failed attempts: Canceling focus and metering, and set the metering point to 0x0 pixels.
camera.getCameraControl().cancelFocusAndMetering();//.setExposureCompensationIndex(12);
MeteringPointFactory meteringPointFactory = previewView.getMeteringPointFactory();
MeteringPoint meteringPoint = meteringPointFactory.createPoint(0,0, 0);
FocusMeteringAction action = new FocusMeteringAction.Builder(meteringPoint).build();
//.setAutoCancelDuration(1, TimeUnit.MICROSECONDS).build();
cameraControl.startFocusAndMetering(action);

Adjusting brightness in android camera api like default camera on touching the camera screen

I am preparing a custom android camera app and wish to adjust the exposure/brightness of the camera on touch event. The default values look a bit darker than the default camera . I tried using whiteBalance(auto) function but it wont help. Was trying it using exposure like
params.setExposureCompensation(params.getExposureCompensation());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
if(params.isAutoExposureLockSupported()) {
params.setAutoExposureLock(false);
}
}
but i am not understanding the difference between the exposure function's like ,
getExposureCompensation(), getMaxExposureCompensation(),getExposureCompensationStep()
Firstly, you are not actually setting the exposure.
params.setExposureCompensation(params.getExposureCompensation());
sets the exposure to the previous value i.e it is never changed. What you need to do is set a value between params.getMinExposureCompensation() and params. getMaxExposureCompensation()
Secondly the difference between the exposure functions is clearly explained in the docs
getExposureCompensation
Gets the current exposure compensation index.
current exposure compensation index. The range is getMinExposureCompensation() to getMaxExposureCompensation(). 0 means exposure is not adjusted.
getMaxExposureCompensation
Gets the maximum exposure compensation index.(>=0)
getExposureCompensationStep
exposure compensation step. Applications can get EV by multiplying the exposure compensation index and step. Ex: if exposure compensation index is -6 and step is 0.333333333, EV is -2.
Here EV stands for exposure value

Android camera, how to set the upper limit of exposure time?

My android application captures preview frames. It is necessary that the frames be not blurred.
This requires to limit the exposure time of the sensor. For example, I want the exposure time be less than 10ms, and the white-balance adjuster uses ISO only.
The only solution I found is the fixing of SENSOR_EXPOSURE_TIME and SENSOR_SENSITIVITY:
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result)
{
// measure ISO and exposure
mExposure = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
mSensitivity = result.get(CaptureResult.SENSOR_SENSITIVITY);
...
}
void prepareCapturing()
{
// setting the necessary values of ISO and exposure
if (mExposure > 10.0 * 1e+6)
{
double exposure = 10.0 * 1e+6;
double sens = mExposure * mSensitivity / exposure;
mPreviewRequestBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, (long)exposure);
mPreviewRequestBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, (int)sens);
}
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
setRepeatingRequest();
}
I call the method prepareCapturing before running my algorithm of preview frame analyzing.
This approach works, but it requires to disable android.control.aeMode, thus the white balance will be off.
Also I tried to use standard scene modes like CONTROL_SCENE_MODE_ACTION, and CONTROL_SCENE_MODE_SPORTS, but exposure time anyway is about 40ms.
The question: is it possible using camera2 intereace to limit exposure time of the sensor, s.t. the white balance be active?
The primary API to require auto-exposure to remain below some maximum exposure time is the CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE control. For example, if you set that to (30,30), then the camera device may not use exposure times longer than 1/30th of a second.
The list of available ranges for a device is provided by CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES.
There's no direct control for setting max/min exposure values by themselves, and if no available target FPS range limits exposure times enough, your only other option is to use manual exposure control (if supported).
Whether that disables AWB is device-dependent, unfortunately - on some devices, the output of the auto-exposure routine is essential for the white balance algorithm to work.
You can know the lower and upper values supported by your phone using the key SENSOR_INFO_EXPOSURE_TIME_RANGE
Check out the next method:
/**
* Get exposure time range.
*
* #param cameraCharacteristics The properties of the camera.
* #return Long exposure compensation range.
* #see <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#SENSOR_INFO_EXPOSURE_TIME_RANGE">
* CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE</a>
*/
private static Range<Long> getExposureTimeRange(CameraCharacteristics cameraCharacteristics) {
return cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);
}
Check out Camera parameters' setExposureCompensation() method.
Here is the URL https://developer.android.com/reference/android/hardware/Camera.Parameters.html#setExposureCompensation(int)

Android Camera2 API manual exposure change

According to offical google team statement the CONTROL_AE_EXPOSURE_COMPENSATION manual change is broken on Android 5.1. I'm lookin for a workaround for couple of days and the only one I found is connected to SENSOR_INFO_SENSITIVITY_RANGE. However, I found some difficulties in using it. My code look like this:
if(!modeDisabled){
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
modeDisabled=true;
}
range1 = characteristics.get(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE);
minmin = range1.getLower();
maxmax = range1.getUpper();
int iso = ((i * (maxmax - minmin)) / 100 + minmin);
mPreviewRequestBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, iso);
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null, mBackgroundHandler);
Of course the 'i' value is a progress value taken from the seekbar and everyting is closed in OnProgressChanged function.
The problem is that there are no visible changes when manipulating the seekbar. I'd be really gratetful for any help.
CONTROL_AE_EXPOSURE_COMPENSATION isn't broken in Android 5.1 in general, it was disabled on the Nexus 6 only (and will be re-enabled in a future update).
If you're disabling auto-exposure, you probably also need to set the exposure time, in addition to the sensitivity. You also preferably need to set the frame duration, though the defaults for both are probably 1/30s, which is reasonable. You can also copy the latest values for those from the most-recent capture result that did you auto-exposure.
That said, you should still see some sort of change here. Is it possible that you're overwriting your capture request elsewhere right after you set this one as the repeating request? You can check the returned capture results to see what the sensitivity setting the camera device is receiving is.

Is it possible that phone camera shoots video with irregular fps?

My goal is to synchronize movie’s frames with device orientation data from phone’s gyroscope/accelerometer. Android provides orientation data with proper timestamps. As for a video its frame rate known only in general. Experiments show that changes in orientation measured by accelerometer don’t match changes in the scene. Sometimes it goes faster, sometimes it goes slower during the same video.
Is there any way to find out how much time passed between two consequent frames?
I’m going to answer this question myself.
First, yes, it is possible that fps or frame rate is not constant. Here is the quote from Android Developers Guide: “NOTE: On some devices that have auto-frame rate, this sets the maximum frame rate, not a constant frame rate.”
http://developer.android.com/reference/android/media/MediaRecorder.html#setVideoFrameRate%28int%29
Second, there is a function get(CV_CAP_PROP_POS_MSEC) in OpenCV VideoCapture class that allows reading current frame time position:
VideoCapture capture("test.mp4");
double curFrameTime;
double prevFrameTime = 0;
double dt;
while (capture.grab())
{
curFrameTime = capture.get(CV_CAP_PROP_POS_MSEC); //Current frame position
dt = curFrameTime - prevFrameTime; //Time difference
prevFrameTime = curFrameTime; //Previous frame position
}
capture.release();
If there is a better suggestion I’ll be glad to see it.

Categories

Resources