Android Camera Angle returning Pi - android

I need to get the camera's horizontal and vertical viewing angles for an app I am writing. I used the approach in the second (not the accepted) answer on this question, which was working fine. I do:
Camera.Parameters p = Camera.open().getParameters();
and can then call
Math.toRadians(p.getVerticalViewAngle());
or the equivalent horizontal method to get the viewing angles.
This worked on my Nexus 4 and on a Samsung tablet, but I decided to try the app on my Nexus 7 and both the horizontal and vertical angles are being returned as pi. Obviously this is a ridiculous value for these attributes. Any idea why I am getting these values for this device?
Also, on a perhaps related note, android.hardware.Camera has been deprecated and replaced by android.hardware.Camera2. I have been unable to find a way of achieving the same goal with Camera2 though, but would welcome any suggestions on how to do this.

The p.getVerticalViewAngle() is probably returning the maximum value for any possible camera.
The answer of pi implies that it has 360° of vision which is improbably but possible and would be the theoretical maximum that a camera could take.
Therefore I would recommend trying to open using the ID:
Camera.Parameters p = Camera.open(/**cameraNumber**/).getParameters();
and checking that the cameraDevice isn't null.
As to the other question, there isn't any way using the camera2 api to get the vertical and horizontal viewing angles, but using the original camera API it does work (at least it's worked for me)

Related

How to use the widest angle lense with Camera2/CameraX API

I am trying to get the cameraId of the widest lense available on the rear side of the device. I am getting the "logical" rear camera just fine, as documented here.
But it defaults to a random rear physical camera that is not the widest camera. I tried to follow the Multi-camera API documentation but for any device I ask if any of the cameras has CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA, it always returns false.
For cameraManager.cameraIdList, I seem to always just get one front and rear camera.
cameraManager.getCameraCharacteristics(cameraId).physicalCameraIds also always returns empty.
cameraManager.getCameraCharacteristics(cameraId).availablePhysicalCameraRequestKeys also always returns empty.
What could I be doing wrong? I am targeting API 29 and running on API 30 devices. Don't want to use deprecated camera API, but it seems like this used to be doable in that API. What other info would you all need?
You can calculate which camera has biggest FOV based on sensor size and focal length.
Fov Angle = 2*atan(l/2d), where l is sensor size and d is focal length.
You can find the math behind this formula here.
https://stackoverflow.com/a/3261794/11861734

How to improve captured image resolution with Camera2 API android?

I am using this project android-camera2-secret-picture-taker to capture image without open camera view, but the captured images is very bad like this
any help to make this better?
thanks
[Edit]
I tried other phones and it works fine, I take this bad images on Huawei Y6II only and I don't know why? the phone camera is 13 mpx and works fine with native camera app.
Did you issue only a single capture request to the camera device? (No free-running preview or such).
Generally, the auto-exposure, focus, and white-balance routines take a second or so of streaming before they stabilize to good values.
Even if you don't want a preview on screen, you need to request 10-30 frames of data from the camera to start before you save a final image. Or to be more robust, set a repeating request targeting some low-resolution SurfaceTexture, and wait until the CaptureResult CONTROL_AE_STATE / AWB_STATE fields reach CONVERGED, and the AF_STATE field is what you want as well (depends on what AF mode you're using). Then capture your image.
This is a wildly blind guess, but hey, worth a try.
If you used some code snippet from the web which suggests to get a list of supported image sizes and just pick the first one - well this has backfired for me on Huawei devices (more than one model) because Huawei seems to provide the list in the ascending order of resolution (i.e. smallest-first), whereas most other devices I've seen does that in descending order (i.e. largest-first).
So if this is a resolution issue, it might be worth a check.

Camera is being rotated 90 degree in air for android

In my AS3 Flex Mobile application for Android, I am using camera and it is being automatically rotated 90 degrees before I even done any video rotation by myself, it seems like it's a known bug in AIR. But I was wondering if anyone found a solution since it's really pretty important feature for mobile application developer.
I've tried to do some rotation manually in my code, but it is only fixes the view on my display, but still sends the wrong video to the receiver.
If any code is required I will add the snippets
Please let me know.
As you mentioned, this is a known bug with AIR. It is not consistent, either. On some devices, it is in the correct orientation but in some (and all iOS devices, I believe, though I haven't fully tested that), it is rotated as you are seeing. For example, it was always oriented correctly on my Nexus 4 and on my Nexus 5, but a friends Moto X is rotated incorrectly.
Unfortunately, I don't believe there is anything you can do short of having the user do a calibration (i.e. overlay a straight line and tell them to place it horizontally and click a button) and rotating the camera display and any images you take with the display.
That being said, if you are using the camera to take photos, I highly recommend using CameraUI instead, which is the native implementation.
I've faced the same issue today but i'm developping in Java, not with AIR so i don't know if it the same, for me the solution was to add this line before starting the recording.
mMediaRecorder.setOrientationHint(90);

Get camera's intrinsic orientation in API <9

In API level 9, Android added the CameraInfo class, which includes information on each physical camera in the device. In particular, it includes an orientation attribute, which is "the angle that the camera image needs to be rotated clockwise so it shows correctly on the display in its natural orientation." This is distinct from the actual rotation of the device, which is found from getContext().getWindowManager().getDefaultDisplay().getRotation().
Android's sample code subtracts the rotation of the device from the orientation of the camera for rear-facing cameras (it's slightly more complicated for front-facing ones), and rotates the camera preview by this amount. This allows the preview to display properly in both portrait and landscape orientations of the screen.
How can I get the intrinsic orientation of the camera in API levels less than 9, where there is no CameraInfo class?
There is some platform specific solutions. But there is no easy general solution.
Android has a Hardware Abstract Layer(HAL), different vendors will implement the HAL differently. For example, different camera device may have different drivers, so they have different ways to get their data out, including your cameraInfo. When Android adds an API into the HAL, it requires its vendors to implement that API based on their hardwares. Then the Android framework and Android application can use that feature in a uniform way.
However, as you said, the getCameraInfo is not in the HAL Before Froyo. So a straightforward approach would be get those info from the driver or platform-specific library yourself.
For MSM Camera, there is a mm_camera_get_camera_info function in liboemcamera.so. You can use it to get a list of camera_info_t structs.
typedef struct {
int modes_supported;
int8_t camera_id;
cam_position_t position;
uint32_t sensor_mount_angle;
}camera_info_t;
The function encapsulates the actual system call to the target camera device. ioctl(controlfd, MSM_CAM_IOCTL_GET_CAMERA_INFO, &cameraInfo). You may directly call it if you like.
So unfortunately, you need to get that info based on the device you are working on. But may be you are expecting a general approach. Then I think the only way to achieve this is to implement the HAL yourself. Many if-else to decide which device or which ioctl command you need to use. Good luck man.

How to set camera resolution in Android with OpenCV?

I'm trying to develop an app for Android, and I would need to get uncompressed pictures with a resolution as high as possible from the camera. I tried takePicture's rawCallback and postviewCallback, but they are not working.
Right now I'm trying with OpenCV (version 2.4) using VideoCapture, but I'm stuck in the default 960x720, which is poor for what I need; and my phone, a Samsung Galaxy S3, is able to provide, theoretically, up to 8Mpx (3,264×2,448 for pictures, and 1,920×1,080 for video, according to Wikipedia). VideoCapture.set(Highgui.CV_CAP_PROP_FRAME_WIDTH/HEIGHT, some number) makes the camera return a black image as far as I've found.
Is there any way to obtain a higher resolution, either through OpenCV or with the Android API, without compressing?
I'm really sorry if this has been asked before; I have been looking for days and I have found nothing.
Thank you for your time!
EDIT: Although it is not exactly what I was asking, I found that there is a way to do something very similar: if you set an OnPreviewCallback for the Camera, using setPreviewCallback, you do get the raw picture data from the camera (at least in the S3 I'm working with). I leave it here in case somebody finds it useful in the future.
EDIT: A partial solution is explained in an answer below. To sum up,
vc.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, desiredFrameWidth);
vc.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, desiredFrameHeight);
works under some conditions; please see below for further detail.
You have to get supported camera preview resoultions by calling getSupportedPreviewSizes.
After this you can set any resolution with method setPreviewSize. And don't forget to setParameters in the end. Actally many OpenCV Android examples contain this information (look at sample3).
In case anybody ever finds this useful, I found a (partial) solution: If your VideoCapture variable is called vc, this should work:
vc.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, desiredFrameWidth);
vc.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, desiredFrameHeight);
Mind that the combination of width and height must be one of the supported picture formats for your camera, otherwise it will just get a black image. You can get those through Camera.Parameters.getSupportedPictureSizes().
However, setting a high resolution appears to exceed the YUV conversion buffer's capacity, so I'm still struggling with that. I'm going to make a new separate question for that, to keep everything clearer: new thread
setPreviewSize does not set picture resolution. setPictureSize does.

Categories

Resources