Android Face Detection dont finding faces - java

I want to find a face on an image from camera. But detector can't find faces. My app does photo and save it in file.
Below code which create file, start camera, and in onActivityResult in trying detect face and save file path to the room, its saving correctrly and showing in recycler view as expected, but face detector dont finding faces. how can i fix this?
private fun takePhoto() {
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if (takePictureIntent.resolveActivity(activity?.packageManager!!) != null) {
val photoFile: File
try {
photoFile = createImageFile()
} catch (e: IOException) {
error { e }
}
val photoURI = FileProvider.getUriForFile(activity?.applicationContext!!, "com.nasibov.fakhri.neurelia.fileprovider", photoFile)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
takePictureIntent.putExtra("android.intent.extras.CAMERA_FACING", 1)
startActivityForResult(takePictureIntent, PhotoFragment.REQUEST_TAKE_PHOTO)
}
}
#Suppress("SimpleDateFormat")
private fun createImageFile(): File {
val date = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
val fileName = "JPEG_$date"
val filesDir = activity?.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
val image = File.createTempFile(fileName, ".jpg", filesDir)
mCurrentImage = image
return mCurrentImage
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_TAKE_PHOTO && resultCode == Activity.RESULT_OK) {
val bitmap = BitmapFactory.decodeFile(mCurrentImage.absolutePath)
val frame = Frame.Builder().setBitmap(bitmap).build()
val detectedFaces = mFaceDetector.detect(frame)
mViewModel.savePhoto(mCurrentImage)
}
}

Android Face detection API tracks face in photos, videos using some landmarks like eyes, nose, ears, cheeks, and mouth.
Rather than detecting the individual features, the API detects the face at once and then if defined, detects the landmarks and classifications. Besides, the API can detect faces at various angles too.
https://www.journaldev.com/15629/android-face-detection

Android SDK contains an API for Face Detection: android.media.FaceDetector class. This class detects faces on the image. To detect faces call findFaces method of FaceDetector class. findFaces method returns a number of detected faces and fills the FaceDetector.Faces[] array. Please note, that findFaces method supports only bitmaps in RGB_565 format at this time.
Each instance of the FaceDetector.Face class contains the following information:
Confidence that it’s actually a face – a float value between 0 and 1.
Distance between the eyes – in pixels.
Position (x, y) of the mid-point between the eyes.
Rotations (X, Y, Z).
Unfortunately, it doesn’t contain a framing rectangle that includes the detected face.
Here is sample source code for face detection. This sample code enables a custom View that shows a saved image from an SD Card and draws transparent red circles on the detected faces.
class Face_Detection_View extends View {
private static final int MAX_FACES = 10;
private static final String IMAGE_FN = "face.jpg";
private Bitmap background_image;
private FaceDetector.Face[] faces;
private int face_count;
// preallocate for onDraw(...)
private PointF tmp_point = new PointF();
private Paint tmp_paint = new Paint();
public Face_Detection_View(Context context) {
super(context);
// Load an image from SD Card
updateImage(Environment.getExternalStorageDirectory() + "/" + IMAGE_FN);
}
public void updateImage(String image_fn) {
// Set internal configuration to RGB_565
BitmapFactory.Options bitmap_options = new BitmapFactory.Options();
bitmap_options.inPreferredConfig = Bitmap.Config.RGB_565;
background_image = BitmapFactory.decodeFile(image_fn, bitmap_options);
FaceDetector face_detector = new FaceDetector(
background_image.getWidth(), background_image.getHeight(),
MAX_FACES);
faces = new FaceDetector.Face[MAX_FACES];
// The bitmap must be in 565 format (for now).
face_count = face_detector.findFaces(background_image, faces);
Log.d("Face_Detection", "Face Count: " + String.valueOf(face_count));
}
public void onDraw(Canvas canvas) {
canvas.drawBitmap(background_image, 0, 0, null);
for (int i = 0; i < face_count; i++) {
FaceDetector.Face face = faces[i];
tmp_paint.setColor(Color.RED);
tmp_paint.setAlpha(100);
face.getMidPoint(tmp_point);
canvas.drawCircle(tmp_point.x, tmp_point.y, face.eyesDistance(),
tmp_paint);
}
}
}

Related

How to list out only either static or animated images in Android?

I want to detect and display most recent images and it should be either animated or static images on user choice.
Also cannot depend on extentions.Because
There would be absence of extention
webp images could be animated or static with same extention (.webp)
It could be wrong extentions
Is there way to identify whether images are animated (webp, gif, apng) or static (jpg, png, webp, etc)?
private static final String[] COLUMNS_OF_INTEREST = new String[]
{
MediaStore.Video.Media._ID,
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.SIZE,
MediaStore.Video.Media.WIDTH,
MediaStore.Video.Media.HEIGHT,
MediaStore.Video.Media.DATE_ADDED
};
public void printGifUri(Context context)
{
ContentResolver cr = context.getContentResolver();
String selection = MediaStore.Images.Media.MIME_TYPE + "=?";
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("webp");
String[] selectionArgsPdf = new String[]{ mimeType };
Cursor gifCursor = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, COLUMNS_OF_INTEREST, selection,selectionArgsPdf,
MediaStore.Images.Media.DATE_ADDED + " DESC");
gifCursor.moveToFirst();
int columnIndexUri = gifCursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
for (int i = 0; i < gifCursor.getCount(); i++)
Log.d("gif file uri -> ", gifCursor.getString(columnIndexUri));
}
I want to also avoid the third party modules as they would increase the size of the app. You can suggest if there is any module available for this with low size.
I have Tried checking the existance of flags like ANIM, VP8, in image file and it works well but this explicit method is time consuming.
The major issue in this is webp as same extention would be static or animated. This makes difficult me to identify the animated and static type.
I think I maybe found a solution... try using
ImageDecoder
the documentation says
If the encoded image is an animated GIF or WEBP, decodeDrawable will
return an AnimatedImageDrawable.
So maybe checking that the result of ImageDecoder.decodeDrawable(source); is an instance of AnimatedImageDrawable should help you figure out if a file is animated or not
such as:
ImageDecoder.Source source = ImageDecoder.createSource(cr,uri);
Drawable drawable = ImageDecoder.decodeDrawable(source);
if (drawable instanceof AnimatedImageDrawable) {
//THE FILE IS ANIMATED
}else{
//THE FILE IS STATIC
}
or such as
private boolean isAnimated(ContentResolver cr,Uri uri){
ImageDecoder.Source source = ImageDecoder.createSource(cr,uri);
Drawable drawable = ImageDecoder.decodeDrawable(cr,source);
return drawable instanceof AnimatedImageDrawable;
}
EDIT:
for API 28 and before, we should use Movie class
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
ImageDecoder.Source source = ImageDecoder.createSource(file);
Drawable drawable = ImageDecoder.decodeDrawable(source);
return drawable instanceof AnimatedImageDrawable;
} else {
Movie movie = Movie.decodeStream(input);
return movie != null;
}
I hope that helps with your problem

How to print password protected PDF in android?

I am printing pdf using the below code which works fine for normal pdfs but crashes with password-protected pdf. is there any way by which we can print password-protected pdf or stop applications from crashing. application crashes even print() called inside a try-catch block.
Exception :
java.lang.RuntimeException:
at android.print.PrintManager$PrintDocumentAdapterDelegate$MyHandler.handleMessage (PrintManager.java:1103)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loop (Looper.java:246)
at android.app.ActivityThread.main (ActivityThread.java:8506)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1139)
code that causing Exception:
val printManager = this.getSystemService(Context.PRINT_SERVICE) as PrintManager
val jobName = this.getString(R.string.app_name) + " Document"
try{
printManager.print(jobName, pda, null)
}
catch(ex:RuntimeException)
{
Toast.makeText(this,"Can't print pdf file",Toast.LENGTH_SHORT).show()
}
PrintDocumentAdapter.kt
var pda: PrintDocumentAdapter = object : PrintDocumentAdapter() {
override fun onWrite(
pages: Array<PageRange>,
destination: ParcelFileDescriptor,
cancellationSignal: CancellationSignal,
callback: WriteResultCallback
) {
var input: InputStream? = null
var output: OutputStream? = null
try {
input = uri?.let { contentResolver.openInputStream(it) }
output = FileOutputStream(destination.fileDescriptor)
val buf = ByteArray(1024)
var bytesRead: Int
if (input != null) {
while (input.read(buf).also { bytesRead = it } > 0) {
output.write(buf, 0, bytesRead)
}
}
callback.onWriteFinished(arrayOf(PageRange.ALL_PAGES))
} catch (ee: FileNotFoundException) {
//Code to Catch FileNotFoundException
} catch (e: Exception) {
//Code to Catch exception
} finally {
try {
input!!.close()
output!!.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
}
override fun onLayout(
oldAttributes: PrintAttributes,
newAttributes: PrintAttributes,
cancellationSignal: CancellationSignal,
callback: LayoutResultCallback,
extras: Bundle
) {
if (cancellationSignal.isCanceled) {
callback.onLayoutCancelled()
return
}
val pdi = PrintDocumentInfo.Builder("Name of file")
.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build()
callback.onLayoutFinished(pdi, true)
}
}
OR if not possible then how to get password removed from pdf.
pdfView.fromAsset(String)
.pages(0, 2, 1, 3, 3, 3) // all pages are displayed by default
.enableSwipe(true) // allows to block changing pages using swipe
.swipeHorizontal(false)
.enableDoubletap(true)
.defaultPage(0)
// allows to draw something on the current page, usually visible in the middle of the screen
.onDraw(onDrawListener)
// allows to draw something on all pages, separately for every page. Called only for visible pages
.onDrawAll(onDrawListener)
.onLoad(onLoadCompleteListener) // called after document is loaded and starts to be rendered
.onPageChange(onPageChangeListener)
.onPageScroll(onPageScrollListener)
.onError(onErrorListener)
.onPageError(onPageErrorListener)
.onRender(onRenderListener) // called after document is rendered for the first time
// called on single tap, return true if handled, false to toggle scroll handle visibility
.onTap(onTapListener)
.onLongPress(onLongPressListener)
.enableAnnotationRendering(false) // render annotations (such as comments, colors or forms)
.password(null)
.scrollHandle(null)
.enableAntialiasing(true) // improve rendering a little bit on low-res screens
// spacing between pages in dp. To define spacing color, set view background
.spacing(0)
.autoSpacing(false) // add dynamic spacing to fit each page on its own on the screen
.linkHandler(DefaultLinkHandler)
.pageFitPolicy(FitPolicy.WIDTH) // mode to fit pages in the view
.fitEachPage(false) // fit each page to the view, else smaller pages are scaled relative to largest page.
.pageSnap(false) // snap pages to screen boundaries
.pageFling(false) // make a fling change only a single page like ViewPager
.nightMode(false) // toggle night mode
.load();
Have you tried updating the ".password" line?
You need not to generate pdf without password to print. as you said you are using barteksc:android-pdf-viewer for viewing pdfs which uses PDfium for rendering pdf which has a method to render bitmap from method.
void getBitmaps() {
ImageView iv = (ImageView) findViewById(R.id.imageView);
ParcelFileDescriptor fd = ...;
int pageNum = 0;
PdfiumCore pdfiumCore = new PdfiumCore(context);
try {
PdfDocument pdfDocument = pdfiumCore.newDocument(fd);
pdfiumCore.openPage(pdfDocument, pageNum);
int width = pdfiumCore.getPageWidthPoint(pdfDocument, pageNum);
int height = pdfiumCore.getPageHeightPoint(pdfDocument, pageNum);
// ARGB_8888 - best quality, high memory usage, higher possibility of OutOfMemoryError
// RGB_565 - little worse quality, twice less memory usage
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.RGB_565);
pdfiumCore.renderPageBitmap(pdfDocument, bitmap, pageNum, 0, 0,
width, height);
//if you need to render annotations and form fields, you can use
//the same method above adding 'true' as last param
iv.setImageBitmap(bitmap);
printInfo(pdfiumCore, pdfDocument);
pdfiumCore.closeDocument(pdfDocument); // important!
} catch(IOException ex) {
ex.printStackTrace();
}
}
store these bitmaps in arraylist and print them using android print framework

OpenCV VideoWriter filps video

I'm using OpenCV 4.5.2 with Java bindings, and trying to create a video from set of frames.
class OpenCVVideoWriter(
size: com.domain.util.model.Size,
frameRate: Float,
outputFile: File
) {
private var videoWriter = VideoWriter(
outputFile.absolutePath,
VideoWriter.fourcc('M', 'J', 'P', 'G'),
frameRate.toDouble(),
Size(size.width.toDouble(), size.height.toDouble()),
true
)
private var currentFrame: Mat = Mat(size.height, size.width, CvType.CV_8UC3)
init {
if (!videoWriter.isOpened) {
throw OpenCVException("Failed to open VideoWriter")
}
currentFrame = Mat(size.height, size.width, CvType.CV_8UC3)
}
fun writeFrame(data: ByteArray) {
currentFrame.put(0, 0, data)
videoWriter.write(currentFrame)
}
fun release() {
videoWriter.release()
currentFrame.release()
}
private companion object {
init {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME)
}
}
}
Frames are OK and I've also dumped the ByteArrays passed to VideoWriter as *.bmp, all of them are fine.
But the final video is flipped (not rotated but flipped vertically):
I've used the same code (but with a bit older version of OpenCV) before in an older project, and it worked correct there (but I can't try it again with that project as I don't have an access to it).
UPD. If I write the frame with OpenCV Imgcodecs.imwrite("/tmp/frame0.jpg", currentFrame), it's flipped too.
How to fix it?

take picture when face detected using FaceDetector google-vision

I found the demo code here: https://github.com/googlesamples/android-vision/blob/master/visionSamples/FaceTracker/app/src/main/java/com/google/android/gms/samples/vision/face/facetracker/FaceTrackerActivity.java
and my question is how to take picture when face detected and save it to device, and when we take 1st picture next picture will be take after 5s when face detected because we can't save to many picture to device.
You have to add FaceDetectionListener in camera API then call startFaceDetection() method,
CameraFaceDetectionListener fDListener = new CameraFaceDetectionListener();
mCamera.setFaceDetectionListener(fDetectionListener);
mCamera.startFaceDetection();
Implement Camera.FaceDetectionListener, you receive the detected face in onFaceDetection override method,
private class MyFaceDetectionListener
implements Camera.FaceDetectionListener {
#Override
public void onFaceDetection(Face[] faces, Camera camera) {
if (faces.length == 0) {
Log.i(TAG, "No faces detected");
} else if (faces.length > 0) {
Log.i(TAG, "Faces Detected = " +
String.valueOf(faces.length));
public List<Rect> faceRects;
faceRects = new ArrayList<Rect>();
for (int i=0; i<faces.length; i++) {
int left = faces[i].rect.left;
int right = faces[i].rect.right;
int top = faces[i].rect.top;
int bottom = faces[i].rect.bottom;
Rect uRect = new Rect(left0, top0, right0, bottom0);
faceRects.add(uRect);
}
// add function to draw rects on view/surface/canvas
}
}
As per your case, new Handler().postDelayed(new Runnable,long seconds) take 2nd picture inside runnable after 5 seconds.
Please let me know if you have any queries.

Android, Java: Scaling .PNG results in low quality

I am creating this game for Android with Java. I am using this code: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html for resizing Bitmaps, I am using .PNG format on all my images. It works really well except that the Bitmaps quality drops quite a lot, even when I scale it down from a larger image. Is this solvable?
You can try out this code.
public static Bitmap shrinkBitmap(String p_file, int p_width, int p_height)
{
BitmapFactory.Options m_bmpFactoryOptions = new BitmapFactory.Options();
m_bmpFactoryOptions.inJustDecodeBounds = true;
Bitmap m_bitmap = BitmapFactory.decodeFile(p_file, m_bmpFactoryOptions);
int m_heightRatio =
(int) Math.ceil(m_bmpFactoryOptions.outHeight / (float) p_height);
int m_widthRatio =
(int) Math.ceil(m_bmpFactoryOptions.outWidth / (float) p_width);
if (m_heightRatio > 1 || m_widthRatio > 1)
{
if (m_heightRatio > m_widthRatio)
{
m_bmpFactoryOptions.inSampleSize = m_heightRatio;
}
else
{
m_bmpFactoryOptions.inSampleSize = m_widthRatio;
}
}
m_bmpFactoryOptions.inJustDecodeBounds = false;
m_bitmap = BitmapFactory.decodeFile(p_file, m_bmpFactoryOptions);
return m_bitmap;
}
EDITED:
Here i have tried out other way also.
Can you please let me know how you are scaling .PNGs so that i can get the idea.

Categories

Resources