Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
E
Ear recognition
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Boston University
Ear recognition
Commits
58ba81e7
Commit
58ba81e7
authored
Sep 24, 2015
by
Josejulio Martínez Magaña
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactors the code a bit to remove unused code.
Adds the keystore.
parent
5ec8178a
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
409 additions
and
620 deletions
+409
-620
app.iml
app/app.iml
+1
-0
build.gradle
app/build.gradle
+1
-0
AndroidManifest.xml
app/src/main/AndroidManifest.xml
+1
-1
CameraActivity.java
.../main/java/com/aluxoft/earrecognition/CameraActivity.java
+0
-505
MainActivity.java
...rc/main/java/com/aluxoft/earrecognition/MainActivity.java
+358
-22
TestConstants.java
app/src/main/java/com/aluxoft/test/TestConstants.java
+23
-0
activity_camera.xml
app/src/main/res/layout/activity_camera.xml
+0
-88
activity_main.xml
app/src/main/res/layout/activity_main.xml
+25
-4
keystore.jks
keystore.jks
+0
-0
No files found.
app/app.iml
View file @
58ba81e7
...
...
@@ -92,6 +92,7 @@
<orderEntry
type=
"sourceFolder"
forTests=
"false"
/>
<orderEntry
type=
"library"
exported=
""
name=
"support-v4-22.0.0"
level=
"project"
/>
<orderEntry
type=
"library"
exported=
""
name=
"support-annotations-22.0.0"
level=
"project"
/>
<orderEntry
type=
"library"
exported=
""
name=
"bolts-android-1.2.1"
level=
"project"
/>
<orderEntry
type=
"library"
exported=
""
name=
"appcompat-v7-22.0.0"
level=
"project"
/>
<orderEntry
type=
"module"
module-name=
"openCVLibrary2411"
exported=
""
/>
</component>
...
...
app/build.gradle
View file @
58ba81e7
...
...
@@ -23,4 +23,5 @@ dependencies {
compile
fileTree
(
dir:
'libs'
,
include:
[
'*.jar'
])
compile
'com.android.support:appcompat-v7:22.0.0'
compile
project
(
':openCVLibrary2411'
)
compile
'com.parse.bolts:bolts-android:1.2.1'
}
app/src/main/AndroidManifest.xml
View file @
58ba81e7
...
...
@@ -21,7 +21,7 @@
</intent-filter>
</activity> -->
<activity
android:name=
".
Camera
Activity"
android:name=
".
Main
Activity"
android:label=
"@string/app_name"
android:screenOrientation=
"portrait"
>
<intent-filter>
...
...
app/src/main/java/com/aluxoft/earrecognition/CameraActivity.java
deleted
100644 → 0
View file @
5ec8178a
package
com
.
aluxoft
.
earrecognition
;
import
android.annotation.SuppressLint
;
import
android.app.AlertDialog
;
import
android.content.Context
;
import
android.content.DialogInterface
;
import
android.content.Intent
;
import
android.content.res.Resources
;
import
android.database.Cursor
;
import
android.graphics.Bitmap
;
import
android.graphics.BitmapFactory
;
import
android.net.Uri
;
import
android.os.Build
;
import
android.os.Bundle
;
import
android.os.Environment
;
import
android.provider.BaseColumns
;
import
android.provider.DocumentsContract
;
import
android.provider.MediaStore
;
import
android.support.v7.app.ActionBarActivity
;
import
android.util.DisplayMetrics
;
import
android.util.Log
;
import
android.view.View
;
import
android.widget.Button
;
import
android.widget.ImageView
;
import
org.opencv.android.Utils
;
import
org.opencv.calib3d.Calib3d
;
import
org.opencv.core.Core
;
import
org.opencv.core.Mat
;
import
org.opencv.core.MatOfByte
;
import
org.opencv.core.MatOfDMatch
;
import
org.opencv.core.MatOfKeyPoint
;
import
org.opencv.core.MatOfPoint2f
;
import
org.opencv.core.Point
;
import
org.opencv.core.Scalar
;
import
org.opencv.core.Size
;
import
org.opencv.core.TermCriteria
;
import
org.opencv.features2d.DMatch
;
import
org.opencv.features2d.DescriptorExtractor
;
import
org.opencv.features2d.DescriptorMatcher
;
import
org.opencv.features2d.FeatureDetector
;
import
org.opencv.features2d.Features2d
;
import
org.opencv.features2d.KeyPoint
;
import
org.opencv.highgui.Highgui
;
import
org.opencv.imgproc.Imgproc
;
import
java.io.File
;
import
java.io.IOException
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
import
java.util.Vector
;
public
class
CameraActivity
extends
ActionBarActivity
{
String
image1
=
"/storage/emulated/0/DCIM/Camera/000_down_ear.jpg"
;
String
image2
=
"/storage/emulated/0/DCIM/Camera/001_front_ear.jpg"
;
String
image3
=
"/storage/emulated/0/DCIM/Camera/000_front_ear.jpg"
;
String
image4
=
"/storage/emulated/0/DCIM/Camera/test_1.png"
;
String
image5
=
"/storage/emulated/0/DCIM/Camera/test_3.png"
;
String
image6
=
"/storage/emulated/0/DCIM/Camera/test_2.png"
;
String
image_patty_01
=
"/storage/emulated/0/DCIM/Camera/PATTY_01.jpg"
;
String
image_patty_02
=
"/storage/emulated/0/DCIM/Camera/PATTY_02.jpg"
;
String
image_elena_01
=
"/storage/emulated/0/DCIM/Camera/ELENA_01.jpg"
;
String
image_elena_02
=
"/storage/emulated/0/DCIM/Camera/ELENA_02.jpg"
;
private
static
final
int
REQUEST_IMAGE_CAPTURE
=
1
;
private
static
final
int
SELECT_PICTURE
=
0
;
private
String
mCurrentPhotoPath
;
private
String
mCurrentPhotoPath1
=
null
;
//image_patty_02;
private
String
mCurrentPhotoPath2
=
null
;
//image_elena_01;
private
String
mCurrentPhotoPath3
=
null
;
//image_elena_02;
private
int
previewWidth
=
150
;
private
int
previewHeight
=
150
;
private
ImageView
previewImage1
;
private
ImageView
previewImage2
;
private
ImageView
previewImage3
;
private
ImageView
previewImage
;
public
void
resizeMat
(
Mat
image
)
{
final
double
kMaxWidth
=
160
;
final
double
kMaxHeight
=
120
;
if
(
image
.
width
()
<=
kMaxWidth
&&
image
.
height
()
<=
kMaxHeight
)
{
return
;
}
double
ratio
=
(
double
)
image
.
width
()
/
(
double
)
image
.
height
();
double
width
,
height
;
if
(
ratio
>
1
)
{
width
=
kMaxWidth
;
height
=
kMaxWidth
*
((
double
)
image
.
height
()/(
double
)
image
.
width
());
}
else
{
height
=
kMaxHeight
;
width
=
kMaxHeight
*
ratio
;
}
Imgproc
.
resize
(
image
,
image
,
new
Size
(
width
,
height
));
}
public
double
distanceFromData
(
DescriptorMatcher
matcher
,
MatOfKeyPoint
keypoints1
,
Mat
descriptors1
,
MatOfKeyPoint
keypoints2
,
Mat
descriptors2
)
{
MatOfDMatch
matches
=
new
MatOfDMatch
();
matcher
.
match
(
descriptors1
,
descriptors2
,
matches
);
DMatch
[]
aMatches
=
matches
.
toArray
();
double
distance
=
0
;
for
(
int
i
=
0
;
i
<
aMatches
.
length
;++
i
)
{
distance
+=
aMatches
[
i
].
distance
;
}
return
distance
;
}
public
void
doOpenCvMagic
()
{
Mat
img1
=
Highgui
.
imread
(
mCurrentPhotoPath1
,
Highgui
.
CV_LOAD_IMAGE_GRAYSCALE
);
resizeMat
(
img1
);
Mat
img2
=
Highgui
.
imread
(
mCurrentPhotoPath2
,
Highgui
.
CV_LOAD_IMAGE_GRAYSCALE
);
resizeMat
(
img2
);
Mat
img3
=
Highgui
.
imread
(
mCurrentPhotoPath3
,
Highgui
.
CV_LOAD_IMAGE_GRAYSCALE
);
resizeMat
(
img3
);
FeatureDetector
detector
=
FeatureDetector
.
create
(
FeatureDetector
.
SIFT
);
MatOfKeyPoint
keypoints1
=
new
MatOfKeyPoint
();
MatOfKeyPoint
keypoints2
=
new
MatOfKeyPoint
();
MatOfKeyPoint
keypoints3
=
new
MatOfKeyPoint
();
detector
.
detect
(
img1
,
keypoints1
);
detector
.
detect
(
img2
,
keypoints2
);
detector
.
detect
(
img3
,
keypoints3
);
Mat
descriptors1
=
new
Mat
();
Mat
descriptors2
=
new
Mat
();
Mat
descriptors3
=
new
Mat
();
DescriptorExtractor
extractor
=
DescriptorExtractor
.
create
(
DescriptorExtractor
.
SIFT
);
extractor
.
compute
(
img1
,
keypoints1
,
descriptors1
);
extractor
.
compute
(
img2
,
keypoints2
,
descriptors2
);
extractor
.
compute
(
img3
,
keypoints3
,
descriptors3
);
DescriptorMatcher
matcher
=
DescriptorMatcher
.
create
(
DescriptorMatcher
.
BRUTEFORCE
);
Mat
outImg1
=
new
Mat
();
Mat
outImg2
=
new
Mat
();
Mat
outImg3
=
new
Mat
();
double
distance13
=
distanceFromData
(
matcher
,
keypoints3
,
descriptors3
,
keypoints1
,
descriptors1
);
double
distance23
=
distanceFromData
(
matcher
,
keypoints3
,
descriptors3
,
keypoints2
,
descriptors2
);
String
message
=
""
;
if
(
distance13
<
distance23
)
{
message
=
"It's more likely to be the subject 1"
;
}
else
if
(
distance23
<
distance13
)
{
message
=
"It's more likely to be the subject 2"
;
}
else
{
message
=
"Both subjects are equally likely"
;
}
new
AlertDialog
.
Builder
(
this
)
.
setTitle
(
"Identification"
)
.
setMessage
(
message
)
.
setPositiveButton
(
android
.
R
.
string
.
ok
,
new
DialogInterface
.
OnClickListener
()
{
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
}
})
.
setIcon
(
android
.
R
.
drawable
.
ic_dialog_info
)
.
show
();
Features2d
.
drawKeypoints
(
img1
,
keypoints1
,
outImg1
);
Features2d
.
drawKeypoints
(
img2
,
keypoints2
,
outImg2
);
Features2d
.
drawKeypoints
(
img3
,
keypoints3
,
outImg3
);
Bitmap
bitmap
=
Bitmap
.
createBitmap
(
outImg1
.
cols
(),
outImg1
.
rows
(),
Bitmap
.
Config
.
ARGB_8888
);
Utils
.
matToBitmap
(
outImg1
,
bitmap
);
previewImage1
.
setImageBitmap
(
bitmap
);
bitmap
=
Bitmap
.
createBitmap
(
outImg2
.
cols
(),
outImg2
.
rows
(),
Bitmap
.
Config
.
ARGB_8888
);
Utils
.
matToBitmap
(
outImg2
,
bitmap
);
previewImage2
.
setImageBitmap
(
bitmap
);
bitmap
=
Bitmap
.
createBitmap
(
outImg3
.
cols
(),
outImg3
.
rows
(),
Bitmap
.
Config
.
ARGB_8888
);
Utils
.
matToBitmap
(
outImg3
,
bitmap
);
previewImage3
.
setImageBitmap
(
bitmap
);
/*
for (int i=0;i<aMatches.length;++i) {
double dist = aMatches[i].distance;
if (dist < min_dist) {
min_dist = dist;
}
if (dist > max_dist) {
max_dist = dist;
}
}
Vector<DMatch> vgood_matches = new Vector<DMatch>();
for (int i=0;i<aMatches.length;++i) {
if (aMatches[i].distance < 3*min_dist) {
vgood_matches.add(aMatches[i]);
}
}
MatOfDMatch good_matches = new MatOfDMatch();
good_matches.fromList(vgood_matches);
Mat image_matches = new Mat();
Features2d.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, image_matches, Scalar.all(-1), Scalar.all(-1), new MatOfByte(), Features2d.NOT_DRAW_SINGLE_POINTS);
Bitmap bitmap = Bitmap.createBitmap(image_matches.cols(), image_matches.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(image_matches, bitmap);
previewImage1.setImageBitmap(bitmap);*/
}
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
System
.
loadLibrary
(
"opencv_java"
);
System
.
loadLibrary
(
"nonfree"
);
setContentView
(
R
.
layout
.
activity_camera
);
previewImage1
=
(
ImageView
)
findViewById
(
R
.
id
.
imageView
);
previewImage2
=
(
ImageView
)
findViewById
(
R
.
id
.
imageView2
);
previewImage3
=
(
ImageView
)
findViewById
(
R
.
id
.
imageView3
);
final
Button
takeButton
=
(
Button
)
findViewById
(
R
.
id
.
button
);
takeButton
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
previewImage
=
previewImage1
;
takePhoto
(
takeButton
);
mCurrentPhotoPath1
=
mCurrentPhotoPath
;
}
});
final
Button
pickButton
=
(
Button
)
findViewById
(
R
.
id
.
button2
);
pickButton
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
previewImage
=
previewImage2
;
takePhoto
(
takeButton
);
mCurrentPhotoPath2
=
mCurrentPhotoPath
;
}
});
final
Button
toIdentifyButton
=
(
Button
)
findViewById
(
R
.
id
.
toidentify
);
toIdentifyButton
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
previewImage
=
previewImage3
;
takePhoto
(
takeButton
);
mCurrentPhotoPath3
=
mCurrentPhotoPath
;
}
});
final
Button
processButton
=
(
Button
)
findViewById
(
R
.
id
.
button3
);
processButton
.
setOnClickListener
(
new
View
.
OnClickListener
(){
@Override
public
void
onClick
(
View
v
)
{
// do opencv magic here...
if
(
mCurrentPhotoPath1
!=
null
&&
mCurrentPhotoPath2
!=
null
&&
mCurrentPhotoPath3
!=
null
)
{
doOpenCvMagic
();
}
}
});
}
public
void
pickPhoto
(
View
view
)
{
Intent
intent
=
new
Intent
();
intent
.
setType
(
"image/*"
);
intent
.
setAction
(
Intent
.
ACTION_GET_CONTENT
);
startActivityForResult
(
Intent
.
createChooser
(
intent
,
"Select Picture"
),
SELECT_PICTURE
);
}
public
void
takePhoto
(
View
view
)
{
Intent
takePictureIntent
=
new
Intent
(
MediaStore
.
ACTION_IMAGE_CAPTURE
);
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
FROYO
)
{
if
(
takePictureIntent
.
resolveActivity
(
getPackageManager
())
!=
null
)
{
File
photoFile
=
null
;
try
{
photoFile
=
createImageFile
();
}
catch
(
IOException
ex
)
{
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if
(
photoFile
!=
null
)
{
takePictureIntent
.
putExtra
(
MediaStore
.
EXTRA_OUTPUT
,
Uri
.
fromFile
(
photoFile
));
startActivityForResult
(
takePictureIntent
,
REQUEST_IMAGE_CAPTURE
);
}
}
}
}
private
File
createImageFile
()
throws
IOException
{
// Create an image file name
String
timeStamp
=
new
SimpleDateFormat
(
"yyyyMMdd_HHmmss"
).
format
(
new
Date
());
String
imageFileName
=
"JPEG_"
+
timeStamp
+
"_"
;
File
storageDir
=
Environment
.
getExternalStoragePublicDirectory
(
Environment
.
DIRECTORY_PICTURES
);
File
image
=
File
.
createTempFile
(
imageFileName
,
/* prefix */
".jpg"
,
/* suffix */
storageDir
/* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath
=
image
.
getAbsolutePath
();
return
image
;
}
@SuppressLint
(
"NewApi"
)
@Override
protected
void
onActivityResult
(
int
requestCode
,
int
resultCode
,
Intent
data
)
{
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
);
if
(
requestCode
==
REQUEST_IMAGE_CAPTURE
)
{
if
(
resultCode
==
RESULT_OK
)
{
if
(
mCurrentPhotoPath
!=
null
)
{
/*
* añadimos la imagen a la galeria
*/
Intent
mediaScanIntent
=
new
Intent
(
Intent
.
ACTION_MEDIA_SCANNER_SCAN_FILE
);
File
f
=
new
File
(
mCurrentPhotoPath
);
Uri
contentUri
=
Uri
.
fromFile
(
f
);
mediaScanIntent
.
setData
(
contentUri
);
this
.
sendBroadcast
(
mediaScanIntent
);
String
path
=
f
.
getAbsolutePath
();
Log
.
e
(
""
,
path
);
Bitmap
galleryImage
=
getBitMapForPreview
(
path
,
previewWidth
,
previewHeight
);
previewImage
.
setImageBitmap
(
galleryImage
);
}
}
}
if
(
requestCode
==
SELECT_PICTURE
)
{
if
(
resultCode
==
RESULT_OK
)
{
int
currentapiVersion
=
android
.
os
.
Build
.
VERSION
.
SDK_INT
;
if
(
currentapiVersion
>=
android
.
os
.
Build
.
VERSION_CODES
.
KITKAT
)
{
Uri
uri
=
data
.
getData
();
String
IMAGE_FILEPATH
=
""
;
try
{
if
(
uri
==
null
)
{
IMAGE_FILEPATH
=
uri
.
getPath
();
}
else
{
// get the id of the image selected by the user
String
wholeID
=
DocumentsContract
.
getDocumentId
(
data
.
getData
());
String
id
=
wholeID
.
split
(
":"
)[
1
];
String
[]
projection
=
{
MediaStore
.
MediaColumns
.
DATA
};
String
whereClause
=
BaseColumns
.
_ID
+
"=?"
;
Cursor
cursor
=
getContentResolver
().
query
(
getUri
(),
projection
,
whereClause
,
new
String
[]
{
id
},
null
);
if
(
cursor
!=
null
)
{
int
column_index
=
cursor
.
getColumnIndexOrThrow
(
MediaStore
.
MediaColumns
.
DATA
);
if
(
cursor
.
moveToFirst
())
{
IMAGE_FILEPATH
=
cursor
.
getString
(
column_index
);
System
.
out
.
println
(
IMAGE_FILEPATH
);
Bitmap
galleryImage
=
getBitMapForPreview
(
IMAGE_FILEPATH
,
previewWidth
,
previewHeight
);
previewImage
.
setImageBitmap
(
galleryImage
);
}
cursor
.
close
();
}
else
{
IMAGE_FILEPATH
=
uri
.
getPath
();
Bitmap
galleryImage
=
getBitMapForPreview
(
IMAGE_FILEPATH
,
previewWidth
,
previewHeight
);
previewImage
.
setImageBitmap
(
galleryImage
);
}
}
}
catch
(
Exception
e
)
{
try
{
Uri
selectedImageUri
=
data
.
getData
();
String
[]
projection
=
{
MediaStore
.
MediaColumns
.
DATA
};
Cursor
cursor
=
managedQuery
(
selectedImageUri
,
projection
,
null
,
null
,
null
);
int
column_index_data
=
cursor
.
getColumnIndexOrThrow
(
MediaStore
.
MediaColumns
.
DATA
);
cursor
.
moveToFirst
();
String
selectedImagePath
=
cursor
.
getString
(
column_index_data
);
Bitmap
galleryImage
=
getBitMapForPreview
(
selectedImagePath
,
previewWidth
,
previewHeight
);
previewImage
.
setImageBitmap
(
galleryImage
);
}
catch
(
Exception
ex
)
{
AlertDialog
.
Builder
builder
=
new
AlertDialog
.
Builder
(
CameraActivity
.
this
);
builder
.
setMessage
(
"El elemento seleccionado no es una imágen válida"
).
setTitle
(
"Información"
);
builder
.
setNegativeButton
(
"Aceptar"
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
id
)
{
// User cancelled the dialog
}
});
AlertDialog
dialog
=
builder
.
create
();
dialog
.
show
();
}
}
}
else
{
try
{
Uri
selectedImageUri
=
data
.
getData
();
String
[]
projection
=
{
MediaStore
.
MediaColumns
.
DATA
};
Cursor
cursor
=
managedQuery
(
selectedImageUri
,
projection
,
null
,
null
,
null
);
int
column_index_data
=
cursor
.
getColumnIndexOrThrow
(
MediaStore
.
MediaColumns
.
DATA
);
cursor
.
moveToFirst
();
String
selectedImagePath
=
cursor
.
getString
(
column_index_data
);
Bitmap
galleryImage
=
getBitMapForPreview
(
selectedImagePath
,
previewWidth
,
previewHeight
);
}
catch
(
Exception
e
)
{
AlertDialog
.
Builder
builder
=
new
AlertDialog
.
Builder
(
CameraActivity
.
this
);
builder
.
setMessage
(
"El elemento seleccionado no es una imágen válida"
).
setTitle
(
"Información"
);
builder
.
setNegativeButton
(
"Aceptar"
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
id
)
{
// User cancelled the dialog
}
});
AlertDialog
dialog
=
builder
.
create
();
dialog
.
show
();
}
}
}
}
}
private
Bitmap
getBitMapForPreview
(
String
path
,
int
width
,
int
height
)
{
BitmapFactory
.
Options
options
=
new
BitmapFactory
.
Options
();
// solo se usa para calcular el samplesize
options
.
inJustDecodeBounds
=
true
;
BitmapFactory
.
decodeFile
(
path
,
options
);
options
.
inSampleSize
=
calculateInSampleSize
(
options
,
(
int
)
convertDpToPixel
((
float
)
width
,
this
),
(
int
)
convertDpToPixel
((
float
)
height
,
this
));
options
.
inJustDecodeBounds
=
false
;
Bitmap
galleryImage
=
BitmapFactory
.
decodeFile
(
path
,
options
);
return
galleryImage
;
}
/**
* esto se utiliza para reducir la carga en memoria de la imagen, android es muy
* ineficiente para cargar imagenes y si no se reduce el tamaño de acuerdo a la resolucion
* del dispositivo, se crean errores de memoria insuficiente, se tienen que obtener el calculo de
* los pixieles en base a los dp de la interfaz y generarlos de acuerdo a la densidad del dispositivo
*
* @param options
* @param reqWidth ancho del imageView donde se metera la imagen en pixeles
* @param reqHeight alto del imageView donde se metera la imagen en pixeles
* @return
*/
private
int
calculateInSampleSize
(
BitmapFactory
.
Options
options
,
int
reqWidth
,
int
reqHeight
)
{
// Raw height and width of image
final
int
height
=
options
.
outHeight
;
final
int
width
=
options
.
outWidth
;
int
inSampleSize
=
1
;
if
(
height
>
reqHeight
||
width
>
reqWidth
)
{
final
int
halfHeight
=
height
/
2
;
final
int
halfWidth
=
width
/
2
;
// Calculate the largest inSampleSize value that is a power of 2 and
// keeps both
// height and width larger than the requested height and width.
while
((
halfHeight
/
inSampleSize
)
>
reqHeight
&&
(
halfWidth
/
inSampleSize
)
>
reqWidth
)
{
inSampleSize
*=
2
;
}
}
return
inSampleSize
;
}
/**
* This method converts dp unit to equivalent pixels, depending on device density.
*
* @param dp A value in dp (density independent pixels) unit. Which we need to convert into pixels
* @param context Context to get resources and device specific display metrics
* @return A float value to represent px equivalent to dp depending on device density
*/
public
static
float
convertDpToPixel
(
float
dp
,
Context
context
){
Resources
resources
=
context
.
getResources
();
DisplayMetrics
metrics
=
resources
.
getDisplayMetrics
();
/**
*
* formulas de android developers:
*
* px = dp * (dpi / 160)
*
* dp = px / (dpi / 160)
*
*/
float
px
=
dp
*
(
metrics
.
densityDpi
/
160
f
);
return
px
;
}
private
Uri
getUri
()
{
String
state
=
Environment
.
getExternalStorageState
();
if
(!
state
.
equalsIgnoreCase
(
Environment
.
MEDIA_MOUNTED
))
return
MediaStore
.
Images
.
Media
.
INTERNAL_CONTENT_URI
;
return
MediaStore
.
Images
.
Media
.
EXTERNAL_CONTENT_URI
;
}
}
app/src/main/java/com/aluxoft/earrecognition/MainActivity.java
View file @
58ba81e7
package
com
.
aluxoft
.
earrecognition
;
import
android.annotation.SuppressLint
;
import
android.app.AlertDialog
;
import
android.app.ProgressDialog
;
import
android.content.Context
;
import
android.content.DialogInterface
;
import
android.content.Intent
;
import
android.support.v7.app.ActionBarActivity
;
import
android.content.res.Resources
;
import
android.graphics.Bitmap
;
import
android.graphics.BitmapFactory
;
import
android.net.Uri
;
import
android.os.Build
;
import
android.os.Bundle
;
import
android.view.Menu
;
import
android.view.MenuItem
;
import
android.os.Environment
;
import
android.provider.MediaStore
;
import
android.support.v7.app.ActionBarActivity
;
import
android.util.DisplayMetrics
;
import
android.util.Log
;
import
android.view.View
;
import
android.widget.Button
;
import
android.widget.ImageView
;
import
org.opencv.android.Utils
;
import
org.opencv.core.Mat
;
import
org.opencv.core.MatOfDMatch
;
import
org.opencv.core.MatOfKeyPoint
;
import
org.opencv.core.Size
;
import
org.opencv.features2d.DMatch
;
import
org.opencv.features2d.DescriptorExtractor
;
import
org.opencv.features2d.DescriptorMatcher
;
import
org.opencv.features2d.FeatureDetector
;
import
org.opencv.features2d.Features2d
;
import
org.opencv.highgui.Highgui
;
import
org.opencv.imgproc.Imgproc
;
import
java.io.File
;
import
java.io.IOException
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
import
java.util.concurrent.Callable
;
import
bolts.Continuation
;
import
bolts.Task
;
public
class
MainActivity
extends
ActionBarActivity
{
ProgressDialog
loading
;
private
static
final
int
REQUEST_IMAGE_CAPTURE
=
1
;
private
String
mCurrentPhotoPath
;
private
String
mCurrentPhotoPath1
=
null
;
private
String
mCurrentPhotoPath2
=
null
;
private
String
mCurrentPhotoPath3
=
null
;
private
int
previewWidth
=
150
;
private
int
previewHeight
=
150
;
private
ImageView
previewImage1
;
private
ImageView
previewImage2
;
private
ImageView
previewImage3
;
private
ImageView
previewImage
;
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
System
.
loadLibrary
(
"opencv_java"
);
System
.
loadLibrary
(
"nonfree"
);
setContentView
(
R
.
layout
.
activity_main
);
Button
camara
=
(
Button
)
findViewById
(
R
.
id
.
button3
);
camara
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
previewImage1
=
(
ImageView
)
findViewById
(
R
.
id
.
imageView
);
previewImage2
=
(
ImageView
)
findViewById
(
R
.
id
.
imageView2
);
previewImage3
=
(
ImageView
)
findViewById
(
R
.
id
.
imageView3
);
final
Button
captureFirstEarButton
=
(
Button
)
findViewById
(
R
.
id
.
button
);
captureFirstEarButton
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
Intent
intent
=
new
Intent
(
MainActivity
.
this
,
CameraActivity
.
class
);
startActivity
(
intent
);
previewImage
=
previewImage1
;
takePhoto
();
mCurrentPhotoPath1
=
mCurrentPhotoPath
;
}
});
final
Button
captureSecondEarButton
=
(
Button
)
findViewById
(
R
.
id
.
button2
);
captureSecondEarButton
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
previewImage
=
previewImage2
;
takePhoto
();
mCurrentPhotoPath2
=
mCurrentPhotoPath
;
}
});
final
Button
captureEarToIdentifyButton
=
(
Button
)
findViewById
(
R
.
id
.
toidentify
);
captureEarToIdentifyButton
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
previewImage
=
previewImage3
;
takePhoto
();
mCurrentPhotoPath3
=
mCurrentPhotoPath
;
}
});
final
Button
processButton
=
(
Button
)
findViewById
(
R
.
id
.
button3
);
processButton
.
setOnClickListener
(
new
View
.
OnClickListener
(){
@Override
public
void
onClick
(
View
v
)
{
// do opencv magic here...
if
(
mCurrentPhotoPath1
!=
null
&&
mCurrentPhotoPath2
!=
null
&&
mCurrentPhotoPath3
!=
null
)
{
Task
.
callInBackground
(
new
Callable
<
Void
>()
{
@Override
public
Void
call
()
throws
Exception
{
doOpenCvMagic
();
return
null
;
}
}).
continueWith
(
new
Continuation
<
Void
,
Void
>()
{
@Override
public
Void
then
(
Task
<
Void
>
task
)
throws
Exception
{
return
null
;
}
});
}
}
});
}
@Override
public
boolean
onCreateOptionsMenu
(
Menu
menu
)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater
().
inflate
(
R
.
menu
.
menu_main
,
menu
);
return
true
;
public
void
takePhoto
()
{
Intent
takePictureIntent
=
new
Intent
(
MediaStore
.
ACTION_IMAGE_CAPTURE
);
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
FROYO
)
{
if
(
takePictureIntent
.
resolveActivity
(
getPackageManager
())
!=
null
)
{
File
photoFile
=
null
;
try
{
photoFile
=
createImageFile
();
}
catch
(
IOException
ex
)
{
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if
(
photoFile
!=
null
)
{
takePictureIntent
.
putExtra
(
MediaStore
.
EXTRA_OUTPUT
,
Uri
.
fromFile
(
photoFile
));
startActivityForResult
(
takePictureIntent
,
REQUEST_IMAGE_CAPTURE
);
}
}
}
}
@SuppressLint
(
"NewApi"
)
@Override
public
boolean
onOptionsItemSelected
(
MenuItem
item
)
{
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int
id
=
item
.
getItemId
();
//noinspection SimplifiableIfStatement
if
(
id
==
R
.
id
.
action_settings
)
{
return
true
;
protected
void
onActivityResult
(
int
requestCode
,
int
resultCode
,
Intent
data
)
{
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
);
if
(
requestCode
==
REQUEST_IMAGE_CAPTURE
)
{
if
(
resultCode
==
RESULT_OK
)
{
if
(
mCurrentPhotoPath
!=
null
)
{
// adds image to device gallery.
Intent
mediaScanIntent
=
new
Intent
(
Intent
.
ACTION_MEDIA_SCANNER_SCAN_FILE
);
File
f
=
new
File
(
mCurrentPhotoPath
);
Uri
contentUri
=
Uri
.
fromFile
(
f
);
mediaScanIntent
.
setData
(
contentUri
);
this
.
sendBroadcast
(
mediaScanIntent
);
String
path
=
f
.
getAbsolutePath
();
Log
.
e
(
""
,
path
);
Bitmap
galleryImage
=
getBitMapForPreview
(
path
,
previewWidth
,
previewHeight
);
previewImage
.
setImageBitmap
(
galleryImage
);
}
}
}
}
public
void
doOpenCvMagic
()
{
Task
.
forResult
(
""
).
continueWith
(
new
Continuation
<
String
,
Void
>()
{
@Override
public
Void
then
(
Task
<
String
>
task
)
throws
Exception
{
loading
=
ProgressDialog
.
show
(
MainActivity
.
this
,
"Matching"
,
"Wait while identifying the image..."
);
loading
.
setCancelable
(
false
);
loading
.
setProgressStyle
(
ProgressDialog
.
STYLE_SPINNER
);
return
null
;
}
},
Task
.
UI_THREAD_EXECUTOR
);
Mat
img1
=
Highgui
.
imread
(
mCurrentPhotoPath1
,
Highgui
.
CV_LOAD_IMAGE_GRAYSCALE
);
resizeMat
(
img1
);
Mat
img2
=
Highgui
.
imread
(
mCurrentPhotoPath2
,
Highgui
.
CV_LOAD_IMAGE_GRAYSCALE
);
resizeMat
(
img2
);
Mat
img3
=
Highgui
.
imread
(
mCurrentPhotoPath3
,
Highgui
.
CV_LOAD_IMAGE_GRAYSCALE
);
resizeMat
(
img3
);
FeatureDetector
detector
=
FeatureDetector
.
create
(
FeatureDetector
.
SIFT
);
MatOfKeyPoint
keypoints1
=
new
MatOfKeyPoint
();
MatOfKeyPoint
keypoints2
=
new
MatOfKeyPoint
();
MatOfKeyPoint
keypoints3
=
new
MatOfKeyPoint
();
detector
.
detect
(
img1
,
keypoints1
);
detector
.
detect
(
img2
,
keypoints2
);
detector
.
detect
(
img3
,
keypoints3
);
Mat
descriptors1
=
new
Mat
();
Mat
descriptors2
=
new
Mat
();
Mat
descriptors3
=
new
Mat
();
DescriptorExtractor
extractor
=
DescriptorExtractor
.
create
(
DescriptorExtractor
.
SIFT
);
extractor
.
compute
(
img1
,
keypoints1
,
descriptors1
);
extractor
.
compute
(
img2
,
keypoints2
,
descriptors2
);
extractor
.
compute
(
img3
,
keypoints3
,
descriptors3
);
DescriptorMatcher
matcher
=
DescriptorMatcher
.
create
(
DescriptorMatcher
.
BRUTEFORCE
);
final
Mat
outImg1
=
new
Mat
();
final
Mat
outImg2
=
new
Mat
();
final
Mat
outImg3
=
new
Mat
();
double
distance13
=
distanceFromData
(
matcher
,
keypoints3
,
descriptors3
,
keypoints1
,
descriptors1
);
double
distance23
=
distanceFromData
(
matcher
,
keypoints3
,
descriptors3
,
keypoints2
,
descriptors2
);
String
message
=
""
;
System
.
out
.
println
(
distance13
);
System
.
out
.
println
(
distance23
);
if
(
distance13
<
distance23
)
{
message
=
"It's more likely to be the subject 1"
;
}
else
if
(
distance23
<
distance13
)
{
message
=
"It's more likely to be the subject 2"
;
}
else
{
message
=
"Both subjects are equally likely"
;
}
return
super
.
onOptionsItemSelected
(
item
);
Features2d
.
drawKeypoints
(
img1
,
keypoints1
,
outImg1
);
Features2d
.
drawKeypoints
(
img2
,
keypoints2
,
outImg2
);
Features2d
.
drawKeypoints
(
img3
,
keypoints3
,
outImg3
);
Task
.
forResult
(
message
).
continueWith
(
new
Continuation
<
String
,
Void
>()
{
@Override
public
Void
then
(
Task
<
String
>
task
)
throws
Exception
{
new
AlertDialog
.
Builder
(
MainActivity
.
this
)
.
setTitle
(
"Identification"
)
.
setMessage
(
task
.
getResult
())
.
setPositiveButton
(
android
.
R
.
string
.
ok
,
new
DialogInterface
.
OnClickListener
()
{
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
}
})
.
setIcon
(
android
.
R
.
drawable
.
ic_dialog_info
)
.
show
();
Bitmap
bitmap
=
Bitmap
.
createBitmap
(
outImg1
.
cols
(),
outImg1
.
rows
(),
Bitmap
.
Config
.
ARGB_8888
);
Utils
.
matToBitmap
(
outImg1
,
bitmap
);
previewImage1
.
setImageBitmap
(
bitmap
);
bitmap
=
Bitmap
.
createBitmap
(
outImg2
.
cols
(),
outImg2
.
rows
(),
Bitmap
.
Config
.
ARGB_8888
);
Utils
.
matToBitmap
(
outImg2
,
bitmap
);
previewImage2
.
setImageBitmap
(
bitmap
);
bitmap
=
Bitmap
.
createBitmap
(
outImg3
.
cols
(),
outImg3
.
rows
(),
Bitmap
.
Config
.
ARGB_8888
);
Utils
.
matToBitmap
(
outImg3
,
bitmap
);
previewImage3
.
setImageBitmap
(
bitmap
);
loading
.
dismiss
();
return
null
;
}
},
Task
.
UI_THREAD_EXECUTOR
);
}
// ------- Helper methods -------
public
void
resizeMat
(
Mat
image
)
{
final
double
kMaxWidth
=
160
;
final
double
kMaxHeight
=
120
;
if
(
image
.
width
()
<=
kMaxWidth
&&
image
.
height
()
<=
kMaxHeight
)
{
return
;
}
double
ratio
=
(
double
)
image
.
width
()
/
(
double
)
image
.
height
();
double
width
,
height
;
if
(
ratio
>
1
)
{
width
=
kMaxWidth
;
height
=
kMaxWidth
*
((
double
)
image
.
height
()/(
double
)
image
.
width
());
}
else
{
height
=
kMaxHeight
;
width
=
kMaxHeight
*
ratio
;
}
Imgproc
.
resize
(
image
,
image
,
new
Size
(
width
,
height
));
}
public
double
distanceFromData
(
DescriptorMatcher
matcher
,
MatOfKeyPoint
keypoints1
,
Mat
descriptors1
,
MatOfKeyPoint
keypoints2
,
Mat
descriptors2
)
{
MatOfDMatch
matches
=
new
MatOfDMatch
();
matcher
.
match
(
descriptors1
,
descriptors2
,
matches
);
DMatch
[]
aMatches
=
matches
.
toArray
();
double
distance
=
0
;
for
(
int
i
=
0
;
i
<
aMatches
.
length
;++
i
)
{
distance
+=
aMatches
[
i
].
distance
;
}
return
distance
;
}
private
File
createImageFile
()
throws
IOException
{
// Create an image file name
String
timeStamp
=
new
SimpleDateFormat
(
"yyyyMMdd_HHmmss"
).
format
(
new
Date
());
String
imageFileName
=
"JPEG_"
+
timeStamp
+
"_"
;
File
storageDir
=
Environment
.
getExternalStoragePublicDirectory
(
Environment
.
DIRECTORY_PICTURES
);
File
image
=
File
.
createTempFile
(
imageFileName
,
/* prefix */
".jpg"
,
/* suffix */
storageDir
/* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath
=
image
.
getAbsolutePath
();
return
image
;
}
private
Bitmap
getBitMapForPreview
(
String
path
,
int
width
,
int
height
)
{
BitmapFactory
.
Options
options
=
new
BitmapFactory
.
Options
();
// Just used to compute the sample size.
options
.
inJustDecodeBounds
=
true
;
BitmapFactory
.
decodeFile
(
path
,
options
);
options
.
inSampleSize
=
calculateInSampleSize
(
options
,
(
int
)
convertDpToPixel
((
float
)
width
,
this
),
(
int
)
convertDpToPixel
((
float
)
height
,
this
));
options
.
inJustDecodeBounds
=
false
;
Bitmap
galleryImage
=
BitmapFactory
.
decodeFile
(
path
,
options
);
return
galleryImage
;
}
/**
* This is used to decreases the image memory load, android is inefficient loading images
* and if you don't reduce the size accordingly to the resolution of the widget, it will have
* memory errors, it has to compute the pixels using the dpi of the screen and generate them
* according to the device screen density.
*
* @param options
* @param reqWidth width of the imageView
* @param reqHeight height of the imageView
* @return
*/
private
int
calculateInSampleSize
(
BitmapFactory
.
Options
options
,
int
reqWidth
,
int
reqHeight
)
{
// Raw height and width of image
final
int
height
=
options
.
outHeight
;
final
int
width
=
options
.
outWidth
;
int
inSampleSize
=
1
;
if
(
height
>
reqHeight
||
width
>
reqWidth
)
{
final
int
halfHeight
=
height
/
2
;
final
int
halfWidth
=
width
/
2
;
// Calculate the largest inSampleSize value that is a power of 2 and
// keeps both
// height and width larger than the requested height and width.
while
((
halfHeight
/
inSampleSize
)
>
reqHeight
&&
(
halfWidth
/
inSampleSize
)
>
reqWidth
)
{
inSampleSize
*=
2
;
}
}
return
inSampleSize
;
}
/**
* This method converts dp unit to equivalent pixels, depending on device density.
*
* @param dp A value in dp (density independent pixels) unit. Which we need to convert into pixels
* @param context Context to get resources and device specific display metrics
* @return A float value to represent px equivalent to dp depending on device density
*/
public
static
float
convertDpToPixel
(
float
dp
,
Context
context
){
Resources
resources
=
context
.
getResources
();
DisplayMetrics
metrics
=
resources
.
getDisplayMetrics
();
/**
* android developers equations:
* px = dp * (dpi / 160)
* dp = px / (dpi / 160)
*/
float
px
=
dp
*
(
metrics
.
densityDpi
/
160
f
);
return
px
;
}
}
app/src/main/java/com/aluxoft/test/TestConstants.java
0 → 100644
View file @
58ba81e7
/**
* Created by josejuliomartinez on 24/09/15.
*/
package
com
.
aluxoft
.
test
;
public
class
TestConstants
{
// ----- For testing purposes ----------------------------------------
static
final
String
image1
=
"/storage/emulated/0/DCIM/Camera/000_down_ear.jpg"
;
static
final
String
image2
=
"/storage/emulated/0/DCIM/Camera/001_front_ear.jpg"
;
static
final
String
image3
=
"/storage/emulated/0/DCIM/Camera/000_front_ear.jpg"
;
static
final
String
image4
=
"/storage/emulated/0/DCIM/Camera/test_1.png"
;
static
final
String
image5
=
"/storage/emulated/0/DCIM/Camera/test_3.png"
;
static
final
String
image6
=
"/storage/emulated/0/DCIM/Camera/test_2.png"
;
static
final
String
image_patty_01
=
"/storage/emulated/0/DCIM/Camera/PATTY_01.jpg"
;
static
final
String
image_patty_02
=
"/storage/emulated/0/DCIM/Camera/PATTY_02.jpg"
;
static
final
String
image_elena_01
=
"/storage/emulated/0/DCIM/Camera/ELENA_01.jpg"
;
static
final
String
image_elena_02
=
"/storage/emulated/0/DCIM/Camera/ELENA_02.jpg"
;
// ---------------------------------------------------------------------
}
app/src/main/res/layout/activity_camera.xml
deleted
100644 → 0
View file @
5ec8178a
<ScrollView
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"fill_parent"
android:layout_height=
"fill_parent"
>
<RelativeLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:paddingLeft=
"@dimen/activity_horizontal_margin"
android:paddingRight=
"@dimen/activity_horizontal_margin"
android:paddingTop=
"@dimen/activity_vertical_margin"
android:paddingBottom=
"@dimen/activity_vertical_margin"
tools:context=
".MainActivity"
android:id=
"@+id/MainActivity"
>
<Button
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"Capture First ear"
android:id=
"@+id/button"
android:layout_marginTop=
"47dp"
android:layout_alignParentTop=
"true"
android:layout_alignParentLeft=
"true"
android:layout_alignParentStart=
"true"
android:layout_alignRight=
"@+id/button2"
android:layout_alignEnd=
"@+id/button2"
/>
<Button
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"Capture Second ear"
android:id=
"@+id/button2"
android:layout_centerVertical=
"true"
android:layout_alignParentLeft=
"true"
android:layout_alignParentStart=
"true"
android:layout_below=
"@+id/imageView"
/>
<Button
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"Capture ear to identify"
android:id=
"@+id/toidentify"
android:layout_centerVertical=
"true"
android:layout_alignParentLeft=
"true"
android:layout_alignParentStart=
"true"
android:layout_below=
"@+id/imageView2"
/>
<ImageView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:id=
"@+id/imageView"
android:layout_below=
"@+id/button"
android:layout_alignParentLeft=
"true"
android:layout_alignParentStart=
"true"
android:layout_alignRight=
"@+id/button"
android:layout_alignEnd=
"@+id/button"
android:maxHeight=
"150dp"
/>
<ImageView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:id=
"@+id/imageView2"
android:layout_below=
"@+id/button2"
android:layout_alignParentLeft=
"true"
android:layout_alignParentStart=
"true"
android:layout_alignRight=
"@+id/button2"
android:layout_alignEnd=
"@+id/button2"
android:maxHeight=
"150dp"
/>
<ImageView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:id=
"@+id/imageView3"
android:layout_below=
"@+id/toidentify"
android:layout_alignParentLeft=
"true"
android:layout_alignParentStart=
"true"
android:layout_alignRight=
"@+id/button2"
android:layout_alignEnd=
"@+id/button2"
android:maxHeight=
"150dp"
/>
<Button
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"Identify"
android:id=
"@+id/button3"
android:layout_below=
"@+id/imageView3"
android:layout_alignParentLeft=
"true"
/>
</RelativeLayout>
</ScrollView>
\ No newline at end of file
app/src/main/res/layout/activity_main.xml
View file @
58ba81e7
...
...
@@ -13,7 +13,7 @@
<Button
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"Ca
rgar primera imagen
"
android:text=
"Ca
pture First ear
"
android:id=
"@+id/button"
android:layout_marginTop=
"47dp"
android:layout_alignParentTop=
"true"
...
...
@@ -25,13 +25,23 @@
<Button
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"Ca
rgar segunda imagen
"
android:text=
"Ca
pture Second ear
"
android:id=
"@+id/button2"
android:layout_centerVertical=
"true"
android:layout_alignParentLeft=
"true"
android:layout_alignParentStart=
"true"
android:layout_below=
"@+id/imageView"
/>
<Button
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"Capture ear to identify"
android:id=
"@+id/toidentify"
android:layout_centerVertical=
"true"
android:layout_alignParentLeft=
"true"
android:layout_alignParentStart=
"true"
android:layout_below=
"@+id/imageView2"
/>
<ImageView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
...
...
@@ -54,12 +64,23 @@
android:layout_alignEnd=
"@+id/button2"
android:maxHeight=
"150dp"
/>
<ImageView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:id=
"@+id/imageView3"
android:layout_below=
"@+id/toidentify"
android:layout_alignParentLeft=
"true"
android:layout_alignParentStart=
"true"
android:layout_alignRight=
"@+id/button2"
android:layout_alignEnd=
"@+id/button2"
android:maxHeight=
"150dp"
/>
<Button
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"
Procesar
"
android:text=
"
Identify
"
android:id=
"@+id/button3"
android:layout_below=
"@+id/imageView
2
"
android:layout_below=
"@+id/imageView
3
"
android:layout_alignParentLeft=
"true"
/>
...
...
keystore.jks
0 → 100644
View file @
58ba81e7
File added
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment