I can't find information about face detection on preview in android.hardware.Camera2, would anybody help me with a complete example?
I saw some questions with camera2 examples in github but I can't understand them.
I used Camera2 sample from Google: https://github.com/googlesamples/android-Camera2Basic.
I set face recognition mode to FULL.
mPreviewRequestBuilder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, CameraMetadata.STATISTICS_FACE_DETECT_MODE_FULL);
Also I checked STATISTICS_INFO_MAX_FACE_COUNT and STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES:
int max_count = characteristics.get(
CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT);
int modes [] = characteristics.get(
CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES);
Output: maxCount : 5 , modes : [0, 2]
My CaptureCallback:
private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
private void process(CaptureResult result) {
Integer mode = result.get(CaptureResult.STATISTICS_FACE_DETECT_MODE);
Face [] faces = result.get(CaptureResult.STATISTICS_FACES);
if(faces != null && mode != null)
Log.e("tag", "faces : " + faces.length + " , mode : " + mode );
}
#Override
public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
CaptureResult partialResult) {
process(partialResult);
}
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
TotalCaptureResult result) {
process(result);
} `
Output: faces : 0 , mode : 2
public static final int STATISTICS_FACE_DETECT_MODE_FULL = 2;
Faces length is constantly 0. Looks like it doesn't recognise a face properly or I missed something.
I know approach with FaceDetector. I just wanted to check how it works with new camera2 Face.
I need to detect face on preview of camera2!
I think that you can't use CameraMetadata.STATISTICS_FACE_DETECT_MODE_FULL, because some devices do not support this type of face detection. Please, can you verify if your device support STATISTICS_FACE_DETECT_MODE_FULL?
If the answer is "NO", please try to use STATISTICS_FACE_DETECT_MODE_SIMPLE
Look at this Samsung Example
https://developer.samsung.com/galaxy/camera#techdocs
There is a sample explaining how to use face detection with camera2 API
Related
I am working on an application where I am connecting with the BLE device and sending commands.
One of that commands we have a command for changing the Bluetooth device name.
Communication is working fine, but the problem is when we send the command for changing the name it was working, BLE confirms the input and sends us the output, but when we disconnect and run LE Scan it was showing the same name as the previous, it should show the new name of the device.
If I want to get the latest name of the device I need to open the Bluetooth page manually in the device and scan over there in the scan result it was showing the latest name, when I open the app again which is in the background and its scanning under LE scan function with 10-sec delay, it was showing the new name in the list.
How can I ask Bluetooth manager or system to refresh the cache or refresh data for that Bluetooth device ?.
I don't know it was right to create ticket, but i have created ticket in google issue tracker : https://issuetracker.google.com/issues/233924346
Thanks.
I had the same problem and solved it by reading the new name from the raw scan data. In this way you never have to use device.getName() which returns the old name from the cache. This is Android Java code for the scan callback function.
private ScanCallback newscancallback()
{
ScanCallback scb;
// Device scan callback.
scb = new ScanCallback()
{
#Override
public void onScanResult(int callbackType, ScanResult result)
{
super.onScanResult(callbackType, result);
int n,k,len,getout;
BluetoothDevice dev;
byte[] rec;
StringBuilder nameb;
String name;
dev = result.getDevice();
// do not use dev.getName() which returns cached name
// read current name from raw scan record instead
name = null;
rec = result.getScanRecord().getBytes();
len = rec.length;
nameb = new StringBuilder();
n = 0;
getout = 0;
// search scan record for name
while(n < len-2 && rec[n] != 0 && getout == 0)
{
// rec[n] is length of next item
// rec[n+1] is item type - look for 8 or 9=name
// rec[n+2].. is the name, length rec[n]-1
if(rec[n] > 1 && (rec[n+1] == 8 || rec[n+1] == 9)
{ // found name
for(k = 0 ; k < rec[n]-1 ; ++k)
nameb.append((char)rec[n+2+k]);
name = nameb.toString();
getout = 1;
}
else // go to next item
n += rec[n] + 1;
}
// name is now null or the new name from the scan record
}
#Override
public void onScanFailed(int errcode)
{
}
#Override
public void onBatchScanResults(List<ScanResult> result)
{
}
};
return (scb);
}
As you can see the latest name in the Bluetooth settings of the mobile device, I believe there is no issue with the Bluetooth manager of the system. The issue will be in the scanning function of the code as it is not actually refreshing the scan list yet and it might saved the last known BLE list somewhere in the cache. If you are using third-party library, you might need to check their documentation or codes about how the scan function actually works. There may be like force-refresh option or something in the library. As far as I know, to save the device's battery, there is a delay to actually refresh the scan list.
I use this code to detect if developer options are enabled on a phone or not:
int developerOptions = Settings.Secure.getInt(this.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED , 0);
However, I tested this and it returns the wrong value on a small number devices (some Huawei phones and others...)
Is there another full proof way to detect if developer options are enabled in a device?
I tried this but it doesn't work (I don't want to use that method anyway because it's not elegant, I'm just testing around):
try
{
startActivityForResult(new Intent(android.provider.Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS), 8080);
finishActivity(8080);
// Developer options enabled
}
catch (Exception e)
{
// Developer options disabled
}
My app's minimum API level is 21.
I've taken a look at this question and other similiar ones on SO but I didn't find a fullproof solution. This is not a duplicate question.
You can't do it any more foolproof than Android itself does it:
public static boolean isDevelopmentSettingsEnabled(Context context) {
final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
final boolean settingEnabled = Settings.Global.getInt(context.getContentResolver(),
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
Build.TYPE.equals("eng") ? 1 : 0) != 0;
final boolean hasRestriction = um.hasUserRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES);
final boolean isAdmin = um.isAdminUser();
return isAdmin && !hasRestriction && settingEnabled;
}
Your code was close, but didn't account for
Build.TYPE.equals("eng") ? 1 : 0)
Min API 17 tested on emulator
public boolean isDeveloperModeEnabled(){
if (Integer.valueOf(android.os.Build.VERSION.SDK) >= 17) {
return android.provider.Settings.Secure.getInt(getActivity().getApplicationContext().getContentResolver(),
android.provider.Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
}
return false;
}
Try the code below:
int devOptions = Settings.Secure.getInt(this.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
Build.TYPE.equals("eng") ? 1 : 0);
I'm trying to get a specific user's tweets into Processing and then have them spoken out using the TTS Library, but only have them spoken when a specific value is detected from Arduino over Serial = 491310
I've got the tweets coming into Processing and can have them printed and spoken, and the value 491310 is picked up by Processing, BUT it's the placement of the if Statement ( 'if (sensor == 491310) {') that I'm struggling with, as it currently has no effect - Can anyone solve this one?
Absolute novice here, any help would be great. Thanks.
import twitter4j.util.*;
import twitter4j.*;
import twitter4j.management.*;
import twitter4j.api.*;
import twitter4j.conf.*;
import twitter4j.json.*;
import twitter4j.auth.*;
import guru.ttslib.*;
import processing.serial.*;
TTS tts;
Serial myPort;
int sensor = 0;
void setup() {
tts = new TTS();
myPort = new Serial(this, Serial.list()[0], 9600);
}
void draw() {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setOAuthConsumerKey("XXXX");
cb.setOAuthConsumerSecret("XXXX");
cb.setOAuthAccessToken("XXXX");
cb.setOAuthAccessTokenSecret("XXXX");
java.util.List statuses = null;
Twitter twitter = new TwitterFactory(cb.build()).getInstance();
String userName ="TWITTER HANDLE";
int numTweets = 19;
String[] twArray = new String[numTweets];
try {
statuses = twitter.getUserTimeline(userName);
}
catch(TwitterException e) {
}
if( statuses != null) {
for (int i=0; i<statuses.size(); i++) {
Status status = (Status)statuses.get(i);
if (sensor == 491310) {
println(status.getUser().getName() + ": " + status.getText());
tts.speak(status.getUser().getName() + ": " + status.getText());
}
}
}
}
void serialEvent (Serial myPort) {
int inByte = myPort.read();
sensor = inByte;
print(sensor);
}
Reading from a serial port returns a byte( 8 bit) not a 16 bit integer. The value of 'sensor" cannot be above 255 so never matches 491310. You'll have to do 2 reads to form the 16 bit int.
My guess is that you're hitting twitter's rate limit. Twitter only allows a certain amount of API calls in a given 15 minute window. And since you're calling getUserTimeline() in the draw() function (which happens 60 times per second), you're going to hit that limit pretty fast.
So you're probably getting a TwitterException, but you're just ignoring it. Never use an empty catch block! At least put a call to e.printStackTrace() in there:
catch(TwitterException e) {
e.printStackTrace();
}
To fix the problem, you're going to have to modify your code to only check for tweets once at the beginning of the program. Move all of your logic for fetching the tweets into the setup() function, and then move the logic for printing them out into the serialEvent() function.
If you still can't get it working, then you're going to have to do some debugging: what is the value of every single variable in your sketch? Use the println() function to help figure that out. Is statuses == null? What is the value of statuses.size()? What is the value of sensor? Once you know that, you'll be able to figure out exactly what's going wrong with your code. But my bet would be it's the twitter rate limit, so check that first.
I am working on Parrot AR. Drone project. The libraries are downloaded and implemented in this project from JavaDrone website (https://code.google.com/p/javadrone/downloads/list). However, although I did included the all the correct libraries and make the right class call to get the method, it still cannot return me the correct information. All the results returned appeared to be "false". Any idea what happening on this code? Please help me :(
So what I did is I have 2 buttons : (i) connect (ii) take off buttons. The Connect button function is for establish connection to drone while Take off button is used for make the drone fly move a bit and return me the drone's NAV navigation data. Sadly all the returned NAV data appears not working.
Note : This code is working fine upon code compilation. But it just cannot return me the correct & valid NAV data from drone.
private void jButtonConnectActionPerformed(java.awt.event.ActionEvent evt) {
System.out.println("Connect?");
drone = new ARDrone();
data = new NavData();
drone.playLED(10,10,10);
drone.connect();
drone.clearEmergencySignal();
System.err.println("Ready to connect!!");
// Wait until drone is ready
drone.waitForReady(CONNECT_TIMEOUT);
System.err.println("Drone State: " + drone.getState());
// do TRIM operation
drone.trim();
System.err.println("Congratulation! You have connected to Drone!");
System.out.println("You can issue flight commands now!");
batteryStatus.setText("0" + "%");
batteryStatus.setForeground(Color.ORANGE);
batteryStatus.setText("" + data.getBattery());
}
private void jButtonTakeOffActionPerformed(java.awt.event.ActionEvent evt) {
System.err.println("Current Drone State : " + drone.getState().toString());
System.err.println("Taking off");
drone.takeOff();
Thread.sleep(4000);
System.err.println("**********\nMOVE\n**********");
drone.move(0.0f, 150.5f, 500.0f, 0.0f);
Thread.sleep(1000);
System.err.println("******************************************");
System.err.println("Drone Infomation");
System.err.println("Battery Too High ? " + data.isBatteryTooHigh());
System.err.println("Battery Too Low ? " + data.isBatteryTooLow());
System.err.println("Drone Flying ? " + data.isFlying());
System.err.println("Control Received ? " + data.isControlReceived());
System.err.println("Motor Down ? " + data.isMotorsDown());
System.err.println("Not Enough Power ?" + data.isNotEnoughPower());
System.err.println("Trim Received ? " + data.isTrimReceived());
System.err.println("Trim Running? " + data.isTrimRunning());
System.err.println("Trim succeded? " + data.isTrimSucceeded());
System.err.println("PIC Number OK? "+ data.isPICVersionNumberOK());
System.err.println("******************************************");
Thread.sleep(5000);
drone.sendAllNavigationData();
drone.land();
}
Output :
******************************************
Drone Infomation
Battery Life: 0.0%
Battery Too High ? false
Battery Too Low ? false
Drone Flying ? false
Control Received ? false
Motor Down ? false
Not Enough Power ?false
Trim Received ? false
Trim Running? false
Trim succeded? false
PIC Number OK? false
********************************************
Update:
What I did was followed John's suggestion. I did implemented all the neccessary methods and NavDataListener for getting the NavData from drone.
import com.codeminders.ardrone.ARDrone;
import com.codeminders.ardrone.ARDrone.VideoChannel;
import com.codeminders.ardrone.NavData;
import com.codeminders.ardrone.NavDataListener;
public class arDrone extends javax.swing.JFrame implements Runnable, NavDataListener{
public ARDrone drone;
public NavData data = new NavData();
public arDrone(String text) {
//FreeTTS speech text
this.text=text;
}
public arDrone() {
initComponents();
setIcon();
initDrone();
}
private void initDrone() {
try {
drone = new ARDrone();
data = new NavData();
drone.addNavDataListener(this);
} catch (UnknownHostException ex) {
System.err.println(ex);
return;
}
}
public void navDataReceived(NavData nd) {
System.err.println("Testing navDataReceived is running...");
updateBatteryStatus(nd.getBattery());
this.flying.set(nd.isFlying());
}
private void updateBatteryStatus(final int value) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
batteryStatus.setText(value + "%");
if (value < 15) {
batteryStatus.setForeground(Color.RED);
} else if (value < 50) {
batteryStatus.setForeground(Color.ORANGE);
} else {
batteryStatus.setForeground(Color.GREEN);
}
}
});
}
The problem is that you are not doing anything to actually get navdata. You can't just create a NavData object and hope it gets filled in with valid data--It won't.
You need to use the com.codeminders.ardrone.NavDataListener interface.
Implement the NavDataListener interface, and the
navDataReceived method.
Add your listener using the ARDrone
method addNavDataListener.
In your navDataRecieved method
you will receive a NavData object with valid telemetry data.
Do you set the Drone IP address? According to sources the default IP for the drone is 192.168.1.1.
You can call another constructor to set the IP:
drone = new ARDrone(InetAddress.getByName("xxx.xxx.xxx.xxx"));
replace xxx.xxx.xxx.xxx with the actual drone IP.
Here is my code on gist
This camera app is follow Android Official Guide
My device is Nexus 5 with kikat 4.4.2
#Override
public void onFaceDetection(Camera.Face[] faces, Camera camera) {
if (faces.length > 0){
Camera.Face f = faces[0];
Log.v(TAG, ("Detected" + faces.length + "faces,the ID of first face is:" + f.id ));
Log.v(TAG, "leftEye : " + f.leftEye);
Log.v(TAG, "mouth : " + f.mouth);
Log.v(TAG, "rect : " + f.rect);
Log.v(TAG, "rightEye: " + f.rightEye);
mCamera.stopFaceDetection();
}
}
The output above code when detect a human face is:
Detected 1 faces,the ID of first face is:-1
FaceActivity﹕ leftEye : null
FaceActivity﹕ mouth : null
FaceActivity﹕ rect : Rect(-393, 356 - -213, 676)
FaceActivity﹕ rightEye: null
So, I want to know whether my Nexus 5 support FaceDetect?If not, how could it implement Screen Lock with Face Unlock?
I found out the reason for this problem. It's all about RGB_564. Android has an API to recognize the human face, but only RGB_564 bitmaps are supported. Face detection is a very cost intensive action. So by default, the camera's FaceDetect feature only recognizes basic face information, and that was the reason why face.leftEye is null.