I'm trying to subtract background of videostream by making cv::absdiff:
absdiff(rgbvs[i], bgs[i], diffs[i]);
The problem is that android camera makes automatic adjustments of brightness, exposure or something else, so there are huge artifacts even with small brightness changes:
I'm using default android camera api:import android.hardware.Camera; and onPreviewFrame for processing.
I've tried next things to prevent automatic adjustments, but they had no effect - brightness still changes depending on scene:
Camera.Parameters parameters = mCamera.getParameters();
parameters.set("whitebalance", "shade");
parameters.set("iso", "ISO800");
parameters.set("auto-exposure", "frame-average");
parameters.set("brightness-step", "0");
parameters.set("lensshade", "disable");
if(parameters.isAutoExposureLockSupported()) {
parameters.setAutoExposureLock(true);
}
if(parameters.isAutoWhiteBalanceLockSupported()) {
parameters.setAutoWhiteBalanceLock(true);
}
parameters.setPreviewSize(640, 480);
mCamera.setParameters(parameters);
Related
This is coded in NativeScript, so I'll try my best to adapt the scenario to Java. I have created an in-app video view with support to record the video.
This is done as follows:
First I create a SurfaceView that will hold the preview of the camera:
this.mSurfaceView = new android.view.SurfaceView(this._context);
this.mHolder = this.mSurfaceView.getHolder();
this.mHolder.setType(android.view.SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Then I create an instance of the Camera, and sets the video surface:
var mCamera = android.hardware.Camera;
var camera = mCamera.open(1);
this.camera = camera;
this.camera.setDisplayOrientation(90);
var parameters = camera.getParameters();
parameters.setRecordingHint(true);
if( parameters.isVideoStabilizationSupported() ){
parameters.setVideoStabilization(true);
}
camera.setParameters(parameters);
this.camera.setPreviewDisplay(_this.mHolder);
this.camera.startPreview();
this.camera.startFaceDetection();
Now, all is good. I have the camera preview in the view that I want it to be. The color is good and I think the image aspect ratio is good too.
However, when I initiate the recording, as I do with the following code:
this.mediarecorder = new android.media.MediaRecorder();
// Step 1: Unlock and set camera to MediaRecorder
this.camera.unlock();
this.mediarecorder.setCamera(this.camera);
// Step 2: Set sources
this.mediarecorder.setAudioSource(android.media.MediaRecorder.AudioSource.CAMCORDER);
this.mediarecorder.setVideoSource(android.media.MediaRecorder.VideoSource.CAMERA);
//this.mediarecorder.setOutputFormat(android.media.MediaRecorder.OutputFormat.MPEG_4);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
this.mediarecorder.setProfile(android.media.CamcorderProfile.get(android.media.CamcorderProfile.QUALITY_HIGH));
// platform.screen.mainScreen.widthDIPs
// platform.screen.mainScreen.heightDIPs
// Step 4: Set output file
var fileName = "videoCapture_" + new Date() + ".mp4";
var path = android.os.Environment.getExternalStoragePublicDirectory(android.os.Environment.DIRECTORY_DCIM).getAbsolutePath() + "/Camera/" + fileName;
this.file = new java.io.File(path);
this.mediarecorder.setOutputFile(this.file.toString());
this.mediarecorder.setOrientationHint(270);
try {
this.mediarecorder.prepare();
this.mediarecorder.start();
} catch( ex ) {
console.log(ex);
}
Then, the image suddenly becomes darker, and my face (its what's in focus when I'm trying it out) gets wider. So the aspect ratio changes, and so does the lighting somehow.
I have tried setting setPictureSize on the camera parameters, and setVideoSize on the MediaRecorder with no luck. And for the lighting change, I have simply no clue as to whats going on. Now I've been googling myself half way to heaven, and still found nothing, so I hope someone here has got any tip on what to pursue next?
Video recording generally tries to run at a steady frame rate, such as 30fps. Camera preview often slows itself down to 10-15fps to maintain brightness, so if you're in a darker location, video recording will be darker (since it can't expose for longer than 1/30s instead of 1/10s that camera preview can).
Did you call setVideoSize before or after calling setProfile? The setProfile call changes many parameters, including preview size; most video recording sizes are 16:9, and the default camera preview resolution is likely a 4:3 size. So when you start the recording, the aspect ratio switches.
Most video recording apps use 16:9 preview sizes even before starting recording so that they're consistent. You can also record 4:3 video, but that's generally not what people want to see.
I'm working with OpenCV 2.4.9 on Android to track a colored object. Tracking works well but sometimes stops working when Auto White Balance kicks in and readjusts the color temperature of the frame.
Goal
Disable or Lock the Auto White Balance feature
-
Attempted Solution
There does not seem to be an option in the CameraBridgeViewBase object(mOpenCvCameraView in the Sample OpenCV projects) for disabling Auto White Balance. However, there is the option to disable AWB for the Android Camera object.
Camera mCamera = Camera.open( 1 );
Camera.Parameters params = mCamera.getParameters();
params.setAutoWhiteBalanceLock(true);
mCamera.setParameters(params);
I've been trying to set the Auto White Balance Lock with the Camera object and then resume business as usual with the CameraBridgeViewBase object and CvCameraViewListener, such as follows.
Camera mCamera set parameters like above code block ^
mOpenCvCameraView.setCvCameraViewListener(this);
...
public Mat onCameraFrame(CvCameraViewFrame inputFrame) { ... }
But the parameters set for mCamera do not seem to stick to the CvCameraViewFrames, and the camera keeps auto white balancing.
Question
How can one make the Camera object parameters "stick" for the CvCameraViewListener frames?
Hi I had the same problem. You need to set the parameters in the OpenCV source code "JavaCameraView" it should be in your project directory under OpenCV -> Java -> Org -> OpenCv -> Android. In my file there's a comment saying /*Now set Camera Parameters */ and play your params.set.... before the mCamera.setParameters(params).... I hope this is helpful. It didnt seem to work in my main activity either.
I couldn't find any information about that in the android docs.
So here is my question:
When I change one parameter of my camera, do I then have to reset all parameters I have set before or can I be sure that they will not be affected by another call to mCamera.setParameters(params)?
For instance, when I update the zoom value by calling
params.setZoom(zoomValue);
mCamera.setParameters(params);
Will things like white balance or auto focus stay untouched? And if so, can I be sure that this is the case for all android devices?
Thanks!
Right, Camera.setParameters() don't support defaults. That's why we always use the following sequence:
Camera.Parameters params = mCamera.getParameters();
params.setZoom(zoomValue);
mCamera.setParameters(params);
Often, people try to avoid multiple calls to getParameters() by using a member:
private Camera.Parameters mParams;
...
mCamera = Camera.open();
mParams = mCamera.getParameters();
...
params.setZoom(zoomValue);
mCamera.setParameters(params);
But there is one catch: as result of setParameters(), seemingly unrelated parameters may change; next time, if you use the same mParams, this may effect the result (the examples are entirely specific to combination of hardware and system). Therefore I strongly recommend not to use cached camera parameters.
I'm having a problem with the exposure lock in the Android Camera.Parameters class. I'm able to lock the exposure before taking a picture, but upon calling camera.takePicture(shutterCallback, rawCallback, jpegCallback) the exposure starts auto-adjusting again.
Also, getAutoExposureLock() still returns true even though the preview and the final saved images show adjusted exposure.
The Android documentation says the exposure lock won't be changed by taking a picture: http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setAutoExposureLock(boolean)
What am I missing?
I managed to lock exposure compensation on my Galaxy S4
Camera.Parameters parameters = mCamera.getParameters();
parameters.setAutoExposureLock(true);
mCamera.setParameters(parameters);
mCamera.startPreview();
Then in each takePicture callback I basically reset the lock to true
Camera.Parameters parameters = mCamera.getParameters();
parameters.setAutoExposureLock(true);
mCamera.setParameters(parameters);
This manages to do something. All images captured are almost equally bright. Changing exposureCompensation has no effect, but when changing ISO the exposure time is automagically adjusted.
I'll dig some more into this and update this post accordingly.
I have the same problem. That's because camera.takePicture(shutterCallback, rawCallback, jpegCallback) stops the preview; you must call camera.startPreview(); to continue previewing.
I've come accross this myself, I'm assuming its an API error as it works the same for me as for you. Unless you have managed to fix it in the meantime? Let me know!
Resetting the lock to true in takePicture callback doesn't work well on my Samsung Galaxy Note 3. It makes situation a bit better, but still produces images with quite different brightness. Exif inside those jepgs confirm that exposure time varies from 1/120 sec to 1/400 sec.
I also noticed that some jpegs have similar exposure time (1/120 sec) but different brightness value saved in exif. So, my was guess that the image post-processor is the game breaker.
I've dumped all camera parameters via native_getParameters, found image correction parameters and set them all to 5. Those parameters are:
set("min-brightness", 5);
set("max-brightness", 5);
set("contrast", 5);
set("min-contrast", 5);
set("max-contrast", 5);
set("max-saturation", 5);
set("min-saturation", 5);
set("saturation", 5);
Now output is much better. Images almost equally bright. All of 500 test images have exposure time = 1/120 ± 1 (rarely 1/125) and brightness = 5 ± 0.1.
I had the same issue on S3. I ended putting those line at the begining of the callback:
public void onPictureTaken(byte[] data, Camera camera) {
//Relock the camera for S3 device
camera.startPreview();
UnLockCamera(camera);
LockCamera(camera);
// your code
With the two functions below
public void LockCamera(Camera camera){
//stop auto white balance and auto exposure lock
Camera.Parameters params = camera.getParameters();
if (params.isAutoExposureLockSupported()) {
params.setAutoExposureLock (true);
}
if (params.isAutoWhiteBalanceLockSupported()) {
params.setAutoWhiteBalanceLock(true);
}
camera.setParameters(params);
}
public void UnLockCamera(Camera camera){
//stop auto white balance and auto exposure lock
Camera.Parameters params = camera.getParameters();
if (params.isAutoExposureLockSupported()) {
params.setAutoExposureLock (false);
}
if (params.isAutoWhiteBalanceLockSupported()) {
params.setAutoWhiteBalanceLock(false);
}
camera.setParameters(params);
}
I'm developing an android application which uses the camera. I got a problem with surfaceChanged() method. Here is my code.
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.e(TAG, "surfaceChanged");
if (mPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(w, h);
mCamera.setParameters(parameters);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
}
the variable mPreviewRunning is initialized as false at the beginning. program runs just fine with horizontal orientation. but when I rotates the phone to the vertical orientation the screen is rotated and is stretched. I can't understand why it's happened. Please help me to solve this problem.
Camera does not change orientation at all - CCD is soldered to motherboard , and delivers pixels as if it were in landscape mode ( most probably ) however, your activity could be restarted by OS on orientation change, unless you disable it in manifest.
( and your surface view is recreated on this restart )
Look in this project for android demos handling camera management:
https://sourceforge.net/p/javaocr/source/ci/5cb9b4176f40ada57296cce79addd205e4c1405c/tree/demos/camera-utils/src/main/java/net/sf/javaocr/demos/android/utils/camera/CameraManager.java#l85
Your mistake is to set preview size from surface size - do not do this. Camera provides limited set of acceptable preview sizes and is free to ignore other settings ( exact behaviour is device depending)
Preview size means used CCD resolution, and camera software will render it on your surface view in size of the surface view doung scaling as necessary.