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.
Related
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();
So I am making an application where you can take some pictures.
I had everything working as it should besides of the PictureSize.
After you take a picture, the preview is supposed to freeze with the last image taken, just like TakePhoto usually do for you. This works as it should until i do parameters.setPictureSize in this method:
public void setupCameraParameters() {
Camera.Parameters parameters = mCamera.getParameters();
Camera.Size preSize = determineBestPreviewSize(parameters);
Camera.Size picSize = determineBestPictureSize(parameters);
parameters.setPreviewSize(preSize.width, preSize.height);
parameters.setPictureSize(picSize.width, picSize.height);
parameters.setRotation(90);
mCamera.setParameters(parameters);
}
This gives my pictures the correct sizes, however what happends now is that my preview doesn't freeze after TakePhoto is called, it just keeps feeding from my camera.
I have even tried doing mCamera.stopPreviewing() without any freezing images. If i release the camera, the image gets black as it should do so I really am working on the right camera-instance as well.
Is there any documentation I have missed? Have someone else entered this problem before.
EDIT:
So I got back my xperia z3 compact from repair and checked this issue again. On z3 this never is an issue, the code will take a picture and then freeze the preview like I want it to. My other phone was a HTC one (m7).
in my Android app, I observed that the video recorded from the front camera is being recorded with 7-10 fps while the back camera does the job fine, the native camera app does record video from front cam at 29fps.
I use the following function to set the frame rate
myRecorder.setVideoFrameRate(30);
but somehow it records it at 8fps. what is the problem? Also the lighting conditions seem to improve it to 15fps, but I want it to be atleast >25fps how can I achieve this? Can we use NDK for this purpose?
I'm exploring the same problem. Because the MediaRecorder already has a native implementation, using the NDK doesn't seem to be a promising approach to increasing the frames per second. Improving the buffering with setPreviewCallbackWithBuffer as shown in the code at http://www.androidadb.com/source/cellbots-read-only/experimental/android/ioio/samples/ShootOnSight/src/com/cellbots/ioioshoot/CameraView.java.html seems promising but I first would like to get a better understanding of the many camera parameters and how they affect frame rate.
As you surely know, there is a wide range of Android devices with a wide range of camera capabilities. To see the capabilities of your particular front and back cameras, you can use the following code (e.g., setting mCameraId to 0 for rear facing and to 1 for front facing).
Camera mCamera = Camera.open(mCameraId);
Camera.Parameters cp = mCamera.getParameters();
Log.d(TAG, "camera parameters: " + cp.flatten());
For example, here are the camera parameters dumped by my Nexus S (running OS 4.0.4).
NEXUS-S FRONT FACING CAMERA PARAMETERS:
06-16 15:14:16.909: D/SENSORS_PLUS(24583): camera parameters:
picture-size-values=640x480;
preview-fps-range=7500,30000;
min-exposure-compensation=-4;
vertical-view-angle=39.4;
horizontal-view-angle=51.2;
whitebalance=auto;
jpeg-thumbnail-height=120;
jpeg-quality=100;
preview-format-values=yuv420sp,yuv420p;
rotation=0;
jpeg-thumbnail-quality=100;
focus-mode=fixed;
preview-format=yuv420sp;
preview-size=640x480;
focal-length=0.9;
video-frame-format=yuv420p;
picture-format-values=jpeg;
max-exposure-compensation=4;
exposure-compensation=0;
preview-frame-rate-values=15;
exposure-compensation-step=0.5;
preview-frame-rate=15;
effect-values=none,mono,negative,sepia;
focus-mode-values=fixed;
picture-size=640x480;
effect=none;
jpeg-thumbnail-width=160;
whitebalance-values=auto,incandescent,fluorescent,daylight,cloudy-daylight;
picture-format=jpeg;
focus-distances=0.20,0.25,Infinity;
preview-fps-range-values=(7500,30000);
jpeg-thumbnail-size-values=160x120,0x0;
preview-size-values=640x480,320x240,176x144
NEXUS-S REAR FACING CAMERA PARAMETERS:
06-16 15:46:55.315: D/SENSORS_PLUS(24732): camera parameters:
picture-size-values=2560x1920,2048x1536,1600x1200,1280x960,640x480;
preview-fps-range=15000,30000;
min-exposure-compensation=-4;
vertical-view-angle=39.4;
horizontal-view-angle=51.2;
whitebalance=auto;
jpeg-thumbnail-height=240;
scene-mode=auto;
jpeg-quality=100;
preview-format-values=yuv420sp,yuv420p;
rotation=0;
jpeg-thumbnail-quality=100;
focus-mode=auto;
preview-format=yuv420sp;
preview-size=720x480;
focal-length=3.43;
video-frame-format=yuv420p;
picture-format-values=jpeg;
max-exposure-compensation=4;
flash-mode-values=on,off,auto,torch;
exposure-compensation=0;
preview-frame-rate-values=30;
exposure-compensation-step=0.5;
preview-frame-rate=30;
flash-mode=off;
effect-values=none,mono,negative,sepia;
focus-mode-values=auto,infinity,macro;
picture-size=2560x1920;
effect=none;
jpeg-thumbnail-width=320;
whitebalance-values=auto,incandescent,fluorescent,daylight,cloudy-daylight;
scene-mode-values=auto,portrait,landscape,night,beach,snow,sunset,fireworks,sports,party,candlelight;
picture-format=jpeg;
focus-distances=0.10,1.20,Infinity;
preview-fps-range-values=(15000,30000);
jpeg-thumbnail-size-values=320x240,0x0;
preview-size-values=720x480,640x480,352x288,176x144
Following setting works for some mobile for 30 FPS.
Camera.Parameters parms = camera.getParameters();
parms.setRecordingHint(true);
camera.setParameters(parms);
I am creating an Android app to do some image processing techniques with the camera and it needs to be fast. This is the pseudo-code of how the entire system works:
1. loop while not finished
1.1 get image frame
1.2 process image for object detection
2. end loop
I actually have questions on the basics of the Camera class:
Is previewing the perceived image from the camera faster than no previews at all? The former means using SurfaceView to preview the image.
Let's say from the takePicture() method, can the image data array be obtained without the previews?
My real question is, what is the best way to obtain the image data (say, byte[] array) quickly and iteratively after processing the image (as stated on top)?
I planned to use takePicture() method to get the image data, but I need your opinion if this is the only way or if there other better ways.
You can setup a SurfaceView as the Camera's preview display and get the data of every preview frame using the PreviewCallback. This would be better than using takePicture if you don't need the high resolution that takePicture captures. In other words, if you want to capture images of lower quality at a faster rate, use PreviewCallback... if you want to capture images of higher quality at a very slow rate, use takePicture.
As for your questions, I don't think you can take pictures without using a preview display, but i could be wrong.
class MainActivity extends Activity implements Camera.PreviewCallback, SurfaceHolder.Callback {
...
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
camera.setPreviewCallback(this);
...
}
public void onPreviewFrame(byte[] data, Camera camera) {
// image data contained in data... do as you wish
}
}
I'm trying to develop an app which uses the Camera. So far it's been working well, except that I'm unable to force the orientation to be "portrait". It seems to work well if I force all activities to "landscape", because the camera preview seems to fit in landscape.
Is there anyway to use the Camera in portrait mode?
Android devices v2.2 and above contain and API to rotate the display to portrait. Devices below 2.2 are landscape only. Your best bet is to detect if the device is 2.2 and rotate 90 degrees. Fall back on landscape for devices under 2.2. The good news is most Android devices are on 2.2 and above.
Check out my answer here for more info:
Camera is wrong unless keyboard is open
public void surfaceCreated(SurfaceHolder holder)
{
// The Surface has been created, acquire the camera and tell it where to draw.
mCamera = Camera.open();
Parameters params = mCamera.getParameters();
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
{
params.set("orientation", "portrait");
mCamera.setDisplayOrientation(90);
}
try
{
mCamera.setPreviewDisplay(holder);
}
catch (IOException exception)
{
mCamera.release();
mCamera = null;
}
}
edit: I was in the midst of Adobe AIR for Android development when I answered this question, and looking back at it, I realize this question didn't pertain to Adobe AIR.
Adobe says:
On devices that can change the screen orientation, such as mobile phones, a Video object attached to the camera will only show upright video in a landscape-aspect orientation. Thus, mobile apps should use a landscape orientation when displaying video and should not auto-rotate.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Camera.html
If you do really want to use the camera in portrait mode, my suggestion is to rotate the video object.
Here's some sample code that rotates the video object (_video) by an angle in degrees (source was pulled from elsewhere on stackoverflow):
var matrix:Matrix = _video.transform.matrix;
var rect:Rectangle = _video.getBounds(this);
matrix.translate(- (rect.left + (rect.width/2)), - (rect.top + (rect.height/2)));
matrix.rotate((angle/180)*Math.PI);
matrix.translate(rect.left + (rect.width/2), rect.top + (rect.height/2));
_video.transform.matrix = matrix;