Reputation: 447
I am using google vision API to get the text that is written in a business card but when I click the picture it only recognizes text that is written in a bigger text or I need to take the picture very closely. then it only recognizes. But I need to focus on a phone no or name or address I couldn't get the whole text that is written on a card together.
And instead if I set the picture in an imageView manually that is not captured but in a good resolution then it recognizes perfect. Is this issue is related to resolution? If anyone having a perfect code for this can you send it?
here is my java code
public class MainActivity extends AppCompatActivity {
ImageView imgPic;
TextView tvText;
Button btnClick, btnCapture;
private int REQUEST_IMAGE_CAPTURE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imgPic = findViewById(R.id.img_pic);
tvText = findViewById(R.id.tv_text);
btnClick = findViewById(R.id.btn_click);
btnCapture = findViewById(R.id.btn_capture);
btnCapture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
});
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
imgPic.setImageBitmap(imageBitmap);
TextRecognizer textRecognizer = new TextRecognizer.Builder(getApplicationContext()).build();
if (!textRecognizer.isOperational()) {
Toast.makeText(MainActivity.this, "could not get the text", Toast.LENGTH_SHORT).show();
} else {
Frame frame = new Frame.Builder().setBitmap(imageBitmap).build();
SparseArray<TextBlock> items = textRecognizer.detect(frame);
int size = items.size();
Log.e("size", String.valueOf(size));
// Toast.makeText(MainActivity.this, size, Toast.LENGTH_SHORT).show();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < items.size(); i++) {
TextBlock myItem = items.valueAt(i);
Log.e("hello", myItem.getValue());
sb.append(myItem.getValue());
sb.append("\n");
}
tvText.setText(sb.toString());
}
}
}
}
Here is my xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="capture"
/>
<ImageView
android:id="@+id/img_pic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:textColor="@color/colorAccent"
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp"
/>
</LinearLayout>
</ScrollView>
Upvotes: 1
Views: 60
Reputation: 1945
You should not use photo capture like this. According to documentation - extras.get("data") contains small preview and should not be used for other purposes then showing preview. You should use camera the other way. There is a Kotlin sample from my library. It creates file in DCIM dir and pass to Camera it's URI to use as output:
private fun takePhoto() {
val photoIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
val dirDCIM = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
val storageDir = File(dirDCIM, "/${config.cameraFolderName}/")
if (!storageDir.exists()) storageDir.mkdirs()
currentCameraImageFile = File(storageDir, "photo_${UUID.randomUUID()}.jpg")
val uri =
FileProvider.getUriForFile(this, "$packageName.fileprovider", currentCameraImageFile!!)
photoIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
val resolvedIntentActivities =
packageManager.queryIntentActivities(photoIntent, PackageManager.MATCH_DEFAULT_ONLY)
for (resolvedIntentInfo in resolvedIntentActivities) {
val packageName = resolvedIntentInfo.activityInfo.packageName
grantUriPermission(
packageName,
uri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
)
}
startActivityForResult(photoIntent, PHOTO_REQUEST_CODE)
}
And then check if capture was OK in onActivityResult:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
PHOTO_REQUEST_CODE -> {
val photoFile = currentCameraImageFile ?: return
if (resultCode == Activity.RESULT_OK && photoFile.exists()) {
// Do your stuff
} else {
// If result is not successful - delete temporary photo file
photoFile.delete()
}
currentCameraImageFile = null
}
}
}
EDIT: Forget to add provider code from "application" section of manifest:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/imagepicker_file_paths" />
</provider>
And imagepicker_file_paths.xml for provider (stored in resources in xml directory):
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="imagepicker_images"
path="." />
</paths>
Upvotes: 2