I'm using Android + Opencv(new to opencv) and I'm currently working with real time object detection (the object stays really close to the android device Camera) , and I noticed that the Android camera's autoFocus keeps modifying my frames (kind of 'zoom in' and 'zoom out' effect) which make it harder for me to keep tracking the object.
I need to turn the "AUTO FOCUS" off because in my case the more blurred image input I have, the better, and I also need to turn the AutoWhiteBalance off as well, or maybe set to a different value.
I would like to know how to do it through my OpenCV CameraBridgeViewBase so I could modify the camera's Focus/WhiteBalance settings.
I've trying to find a way to solve it, and I noticed that many people face the same problems.
Here, at Stack Overflow, would be a great place to find someone who have worked with that and found a good way to overcome these problems.
create your own subclass of javacameraview
public class MyJavaCameraView extends JavaCameraView {
where you can have access to mCamera;
add whatever camera access using method you are interested in
for example
// Setup the camera
public void setFlashMode(boolean flashLightON) {
Camera camera = mCamera;
if (camera != null) {
Camera.Parameters params = camera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
and use this new class as part of the main activity
//force java camera
mOpenCvCameraView = (MyJavaCameraView) findViewById(R.id.activity_surface_view);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
mOpenCvCameraView.enableView();
Related
I have created a camera app and using the data to do something .But the data is always in landscape mode .
I have tried this which is making the preview in portrait mode but the byte[] I am getting still gives me a landscape photo.
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
mCamera.setDisplayOrientation(90);
I know I can make it as a bitmap and rotate it 90 but I need only the data from onPictureTaken.
I also tried
param.setRotation(90);
Which is not working on some of the devices.
You are right, this is how camera API works (unlike iOS). There are some efficient methods that can rotate the pixels to portrait if you really need this, but they never come at 0 cost. So the best practice is to adjust your code that processes the arriving preview frames.
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.
In my android app, I am trying to do some image recognition, and I want to open the camera and see the camera generated images before even taking a pic, like the camera browse mode.
Basically as you browse I want to continuously grab the current screen and then read it and generate some object to update some text on the screen. Something like this
#Override
// this gets called every 5 seconds while in camera browse mode. bitmap is the image of the camera currently
public void getScreen(Bitmap bitmap) {
MyData data = myalgorithm(bitmap);
displayCountOnScreen(data);
}
I saw this app https://play.google.com/store/apps/details?id=com.fingersoft.cartooncamera&hl=en
and in camera browse mode, they change the screen and put some other GUI stuff on the screen. I want to do that too.
Anyone know how I can do this?
Thanks
If all you want to do is put some GUI elements on the screen, then there is no need to fetch all the preview frames as Bitmaps (though you could do that as well, if you want):
Create a layout with a SurfaceView for where you want the video data to appear, and then put other views on top.
In onCreate, you can get it like this:
surfaceView = (SurfaceView)findViewById(R.id.cameraSurfaceView);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this); // For when you need to know when it changes.
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
When you create a camera, you need to pass it a Surface to display the preview on, see:
http://developer.android.com/reference/android/hardware/Camera.html#setPreviewDisplay(android.view.SurfaceHolder):
Camera camera = ...
...
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
If you want to do image recognition, what you want are the raw image bytes to work with. In this case, register a PreviewCallback, see here:
http://developer.android.com/reference/android/hardware/Camera.html#setPreviewCallbackWithBuffer(android.hardware.Camera.PreviewCallback)
Using API 14 I have created an Activity which uses face detection successfully (I'm a bit of a newb at this Face Detection stuff).
I don't want to show the preview of the Camera however; I just want to know when the user's face is in front of the camera. I added a few buttons to make the SurfaceView Visible/Invisible and I found that the face detection stops working when it is INVISIBLE or GONE.
Is there a way to enable the face detection without requiring the SurfaceView in the layout?
Here is how I have coded it:
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
if(mCamera.getParameters().getMaxNumDetectedFaces() >0) {
mCamera.setFaceDetectionListener(new Camera.FaceDetectionListener() {
#Override public void onFaceDetection(Face[] faces, Camera camera) {
if(faces.length > 0) {
System.out.println("Found someone");
}
}
});
mCamera.startFaceDetection();
}
To hide the surfaceview I have added a black View. :-)
<View android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000"/>
I've had a reasonable look around and I haven't found much code using startFaceDetection() yet.
Thanks for any ideas / help.
You should rather use a dummy SurfaceTexture for your purposes.
Just create a SurfaceTexture object by passing any integer such as
mSurfaceTexture = new SurfaceTexture(1);
Now, open your camera and do the following:
mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
try{
mCamera.setPreviewTexture(mSurfaceTexture);
}
catch (IOException t) {
//Do Something here
}
3) You can do everything else just the same way i.e. using face detection.
The Camera Preview doesn't get displayed if you omit
setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
I have not yet tested this with Face Detection (no 4.0 device and the emulator doesn't yet support it). But it should work.
Reference: https://groups.google.com/forum/?fromgroups#!topic/android-developers/EzBgJRetaCo
You could also attempt to use setPreviewTexture(SurfaceTexture st) instead of setPreviewDisplay and use a SurfaceTexture that you can control.
I am trying to get a camera preview with a color effect applied to it, such as for example the NEGATIVE effect. There are no errors, and the preview is visible without problems, but independent of the ColorEffect I set - the camera preview remains unchanged. I tested if the effects I am trying to use are available to my phone by running params.getSupportedColorEffects() (also these effects also work in the built in photo app).
I have no idea what is wrong with the code - I am posting it below. Perhaps someone here has an idea what could make this work? Thanks in advance.
public class CustomCameraView extends SurfaceView{
Camera mCamera;
SurfaceHolder mHolder;
public CustomCameraView(Context context){
super(context);
mHolder = this.getHolder();
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mHolder.addCallback(mSurfaceHolderListener);
}
SurfaceHolder.Callback mSurfaceHolderListener = new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
mCamera=Camera.open();
try {
mCamera.setPreviewDisplay(mHolder);
}
catch (Exception e){ }
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
Camera.Parameters params = mCamera.getParameters();
params.setColorEffect(Camera.Parameters.EFFECT_NEGATIVE);
mCamera.setParameters(params);
mCamera.startPreview();
}
public void surfaceDestroyed(SurfaceHolder arg0)
{
mCamera.stopPreview();
mCamera.release();
}
};
}
After some testing it turned out the problem could be related to the HTC Desire I was testing on (or maybe its OS version). The code works correctly on some other Samsung phones. I haven't figured out what could be the problem on the HTC.
UPDATE:
I have managed to get the effects working, but truly by accident, and I still don't understand why. But I will give the answer here - perhaps someone will find it useful, or maybe will be able to explain why it happens this way:
I added the following line to the surfaceChanged method because I was trying to decrease the size of the preview:
previewHolder.setFixedSize(width, height-1);
This had the result of making the selected effect visible.
When I changed this line to:
previewHolder.setFixedSize(width, height);
the effect was not visible any more once again. So odd.... it works for set height being anything less than the received height parameter.
I have been struggling with this as well. I found out that the HTC Desire its camera needs a strange order of executing the setParameters, setPreviewDisplay and startPreview for the color effect to work. The order is:
Camera.Parameters parameters = camera.getParameters();
//set the parameters
camera.setParameters(parameters);
camera.startPreview();
camera.setParameters(parameters);
camera.setPreviewDisplay(surfaceHolder);
Calling startPreview before setPreviewDisplay is documented in the Android SDK as a way of initializing the camera and the surfaceView in parallel.
Regarding your update about getting the effects to work by accident, the same happend to me! I assume for the same reason, some of my code got called twice in quick succesion (in my case due to a changing database object). This caused the method to (re)set the parameters and (re)start the preview to be called twice producing the desired result. After realising this and some more experimenting the above order seemed to work on both my HTC Desire and Acer Iconia A500 and I was quite happy with it.
However I have just received a comment for my application saying it produces corrupted images on the HTC Desire HD so I would recommend not using this order of camera initialization as a default but rather as a fix for the HTC Desire.
After setting new parameters to camera and starting preview invalidate() are calling on your SurfaceView . But it only Invalidate the whole view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future. So there is no guarantees that onDraw() will be called immediately. But onDraw() are always invoking after calling onMeasure() with size differs from current. So it can be a reason of this odd behavior.
Simple answers use following type :
Camera camera = null;
camera = Camera.open();
if (camera != null) {
try {
Camera.Parameters parameters = camera.getParameters();
// Set all kind of stuffs here..
parameters.setSceneMode(Camera.Parameters.FLASH_MODE_AUTO);
parameters.setColorEffect(Camera.Parameters.EFFECT_SEPIA); // whatever effect you want
camera.setParameters(parameters);
camera.setPreviewDisplay(surface_holder);
camera.startPreview();
} catch (IOException exception) {
camera.release();
camera = null;
}
}