Set OCR whitelist in the TextRecognizer - android-vision

I'm analysing the ocr-reader sample project: https://github.com/googlesamples/android-vision/tree/master/visionSamples/ocr-reader
The goal would be to replace my custom "text to image" implementation for Android (with OpenCV and Tesseract) with Android Vision.
I could not find any way to apply advanced configuration for the OCR processor. For example, in my application, only a predefined set of symbols is allowed. For that, I'm using the following code in my App:
api.SetVariable("tessedit_char_whitelist", "ABJOKEA1234");
This helps to avoid the confusion between 0 and O for example.
Is there a way to do this with android-vision? I don't see any options while building the TextRecognizer:
TextRecognizer textRecognizer = new TextRecognizer.Builder(context).build();
In a general matter, does Google plan to extend the configurability of the library? For example:
Cropping of the source image
Providing a custom OCR training file
Or is it supposed to remain a straightforward library, with just common features?
Thanks for your help!

I am also working on that, i am trying to make a business card reader with mobile vision, so far when the text is detected i am using checks with if conditions using strings which are generated in real time..
if (mText == null) {
return;
}
if(mText.getValue().contains("#") && mText.getValue().contains(".") && !mText.getValue().equals(mText.getValue().toUpperCase())){
Log.e("mTextemail",mText.getValue());
email=mText.getValue();
}
if (mText.getValue().startsWith("+")|| mText.getValue().startsWith("0")&& mText.getValue().contains("+-0123456789/-#")&& !mText.getValue().contains("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")){
Log.e("mTextphone",mText.getValue());
phone=mText.getValue();
}
if (!mText.getValue().contains("ABCDEFGHIJKLMNOPQRSTUVWXYZ")&& !mText.getValue().contains("0123456789-/#") && !mText.getValue().contains("abcdefghijklmnopqrstuvwxyz")){
Log.e("mTextcompanyName",mText.getValue());
companyName=mText.getValue();
}if(mText.getValue().startsWith("ABCDEFGHIJKLMNOPQRSTUVWXYZ" )&& mText.getValue().endsWith("abcdefghijklmnopqrstuvwxyz")){
name=mText.getValue();
}
if(name ==null){
name="Was not specified";
}
if(email ==null){
email="Was not specified";
}
if(phone ==null){
phone="Was not specified";
}
if(companyName ==null){
companyName="Was not specified";
}
it prints the logs with 70% accuracy, may be we can help each other and also i want these correct logs to be displayed in an activity i have used interfaces but its not working.
If you have any tips or trick that you have discovered please do share.

Related

system_cpu_usage is Nan when compiled in native

In my quarkus application i'm using micrometer to retrieve metrics (like in this guide : https://quarkus.io/guides/micrometer).
In JVM mode everything works fine, but in native mode system_cpu_usage is "Nan".
I tried bumping micrometer to 1.8.4 and adding :
{
"name":"com.sun.management.OperatingSystemMXBean", "allPublicMethods": true
},
to my reflect-config.json but no luck. I also tried generating the reflect-config (and other native configuration files) with the graalvm tracing agent but still no luck.
This may be a bug.
Micrometer is looking for a few known implementations of the MXBean:
https://github.com/micrometer-metrics/micrometer/blob/b087856355667abf9bf2386265edef8642e0e077/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/system/ProcessorMetrics.java#L55
private static final List<String> OPERATING_SYSTEM_BEAN_CLASS_NAMES = Arrays.asList(
"com.ibm.lang.management.OperatingSystemMXBean", // J9
"com.sun.management.OperatingSystemMXBean" // HotSpot
);
so that it can find the methods that it should be invoking...
https://github.com/micrometer-metrics/micrometer/blob/b087856355667abf9bf2386265edef8642e0e077/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/system/ProcessorMetrics.java#L80
this.operatingSystemBean = ManagementFactory.getOperatingSystemMXBean();
this.operatingSystemBeanClass = getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES);
Method getCpuLoad = detectMethod("getCpuLoad");
this.systemCpuUsage = getCpuLoad != null ? getCpuLoad : detectMethod("getSystemCpuLoad");
this.processCpuUsage = detectMethod("getProcessCpuLoad");
(Note specifically "getFirstClassFound", which is constrained against the first list).
Speculation on my part, but I suspect Graal is returning a different type, which is possible from here:
https://github.com/oracle/graal/blob/6ba65dad76a4f54fa59e1ed2a62dedd3afe39928/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java#L166
would take some digging to know which, but I would open an issue with Micrometer so we can sort it out.

How to add modernizr build so that I can properly check Modernizr.capture? (currently always undefined)

I need to check if the user's device can input from a camera on my site. To do this I am attempting to use modernizr. I have followed the steps/example code provided on their site but when I test the capture attribute, I always get undefined, regardless of if I am on a device that supports capture.
Steps I followed:
I browsed for the input[capture] attribute and added it to the build
I copied the demo code to check this feature and added it to my project
I downloaded the build, added the js file to my project, and included the appropriate reference in my page
However after all of this, when inspecting Modernizr.capture in the chrome inspector, it always shows up as undefined.
My basic check function is as follows:
$scope.hasCamera = function() {
if (Modernizr.capture) {
// supported
return true;
} else {
// not-supported
return false;
}
}
This is my first time using Modernizr. Am I missing a step or doing something incorrectly? I also installed modernizr using npm install and tried adding the reference to a json config file from the command line.
Alternatively, how might I check if my device has a camera?
Thank you very much for your time. Please let me know if I am being unclear or if you need any additional information from me.
A few things
while photos are helpful, actual code hosted in a public website (either your own project, or on something like jsbin.com) is 10x as useful. As a result, I am not sure why it is coming back as undefined.
The actual capture detect is quite simple. It all comes down to this
var capture = 'capture' in document.createElement('input')`
Your code is a lot more complicated than it needs to be. Lets break it down. You trying to set $scope.hasCamera to equal the result of Modernizr.capture, and you are using a function to check the value of Modernizr.capture, and if it is true, return true. If it is false, return false. There is a fair bit of duplicated logic, so we can break it down from the inside out.
Firstly, your testing for a true/false value, and then returning the same value. That means you could simplify the code by just returning the value of Modernizr.capture
$scope.hasCamera = function() {
return Modernizr.capture
}
While Modernizr will always be giving you a boolean value (when it is functioning - without seeing your actual code I can't say why it is coming back as undefined), if you are unsure of the value you can add !! before it to coerce it into a boolean. In your case, it would make undefined into false
$scope.hasCamera = function() {
return !!Modernizr.capture
}
At this point, you can see that we are setting up a function just to return a static value. That means we can just set assign that static value directly to the variable rather than setting up a function to do that
$scope.hasCamera = !!Modernizr.capture
Now, the final thing you may be able to do something better is if you are only using Modernizr for this one feature. Since it is such a simple feature detection, it is overkill to be using all of Modernizr.
$scope.hasCamera = 'capture' in document.createElement('input')`

App Folder files not visible after un-install / re-install

I noticed this in the debug environment where I have to do many re-installs in order to test persistent data storage, initial settings, etc... It may not be relevant in production, but I mention this anyway just to inform other developers.
Any files created by an app in its App Folder are not 'visible' to queries after manual un-install / re-install (from IDE, for instance). The same applies to the 'Encoded DriveID' - it is no longer valid.
It is probably 'by design' but it effectively creates 'orphans' in the app folder until manually cleaned by 'drive.google.com > Manage Apps > [yourapp] > Options > Delete hidden app data'. It also creates problem if an app relies on finding of files by metadata, title, ... since these seem to be gone. As I said, not a production problem, but it can create some frustration during development.
Can any of friendly Googlers confirm this? Is there any other way to get to these files after re-install?
Try this approach:
Use requestSync() in onConnected() as:
#Override
public void onConnected(Bundle connectionHint) {
super.onConnected(connectionHint);
Drive.DriveApi.requestSync(getGoogleApiClient()).setResultCallback(syncCallback);
}
Then, in its callback, query the contents of the drive using:
final private ResultCallback<Status> syncCallback = new ResultCallback<Status>() {
#Override
public void onResult(#NonNull Status status) {
if (!status.isSuccess()) {
showMessage("Problem while retrieving results");
return;
}
query = new Query.Builder()
.addFilter(Filters.and(Filters.eq(SearchableField.TITLE, "title"),
Filters.eq(SearchableField.TRASHED, false)))
.build();
Drive.DriveApi.query(getGoogleApiClient(), query)
.setResultCallback(metadataCallback);
}
};
Then, in its callback, if found, retrieve the file using:
final private ResultCallback<DriveApi.MetadataBufferResult> metadataCallback =
new ResultCallback<DriveApi.MetadataBufferResult>() {
#SuppressLint("SetTextI18n")
#Override
public void onResult(#NonNull DriveApi.MetadataBufferResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Problem while retrieving results");
return;
}
MetadataBuffer mdb = result.getMetadataBuffer();
for (Metadata md : mdb) {
Date createdDate = md.getCreatedDate();
DriveId driveId = md.getDriveId();
}
readFromDrive(driveId);
}
};
Job done!
Hope that helps!
It looks like Google Play services has a problem. (https://stackoverflow.com/a/26541831/2228408)
For testing, you can do it by clearing Google Play services data (Settings > Apps > Google Play services > Manage Space > Clear all data).
Or, at this time, you need to implement it by using Drive SDK v2.
I think you are correct that it is by design.
By inspection I have concluded that until an app places data in the AppFolder folder, Drive does not sync down to the device however much to try and hassle it. Therefore it is impossible to check for the existence of AppFolder placed by another device, or a prior implementation. I'd assume that this was to try and create a consistent clean install.
I can see that there are a couple of strategies to work around this:
1) Place dummy data on AppFolder and then sync and recheck.
2) Accept that in the first instance there is the possibility of duplicates, as you cannot access the existing file by definition you will create a new copy, and use custom metadata to come up with a scheme to differentiate like-named files and choose which one you want to keep (essentially implement your conflict merge strategy across the two different files).
I've done the second, I have an update number to compare data from different devices and decide which version I want so decide whether to upload, download or leave alone. As my data is an SQLite DB I also have some code to only sync once updates have settled down and I deliberately consider people updating two devices at once foolish and the results are consistent but undefined as to which will win.

ffmpeg code (API)

I started to deal with ffmpeg API ( not the command prompt ) to build a movie editor, and I'm trying to find a good tutorial about how to extract keyframes from video, but I didn't find it.
Someone did it before and can write the code here?
Someone has a good tutorial about ffmpeg API?
Thank you!
In your demuxing loop, check for the AV_PKT_FLAG_KEY flag in AVPacket::flags after calling av_read_frame() with your AVFormatContext and confirming the read packet is from the correct stream of the input. Example:
AVPacket packet;
if (av_read_frame(pFormatCtx, &packet) < 0) {
break;
}
if (videoStream/* e.g. 0 or 1 */ == packet.stream_index) {
if (packet.flags & AV_PKT_FLAG_KEY) { //do something
Note that, in my experience, you sometimes need to decode up to 2 keyframes before the desired frame in order to produce a good picture.
See the doc/examples directory in the ffmpeg distribution for some API usage examples, e.g. demuxing_decoding.c. You can also reference ffmpeg.c (the source of the famous CLI) if you are brave and/or have a good IDE.

Hadoop Map reduce Testing - custom record reader

I have written a custom record reader and looking for sample test code to test my custom reader using MRUnit or any other testing framework. Its working fine as per the functionality but I would like to add test cases before I make an install. Any help would be appreciable.
In my opinion, a custom record reader is like any iterator. For testing my record reader I have been able to work without MRUnit or any other hadoop junit frameworks. The test executes quickly and the footprint is small too. Initialize the record reader in your test case and keep iterating on it. Here is a pseudocode from one of my tests. I can provide you more details if you want to proceed in this direction.
MyInputFormat myInputFormat = new MyInputFormat();
//configure job and provide input format configuration
Job job = Job.getInstance(conf, "test");
conf = job.getConfiguration();
// verify split type and count if you want to verify the input format also
List<InputSplit> splits = myInputFormat.getSplits(job);
TaskAttemptContext context = new TaskAttemptContextImpl(conf, new TaskAttemptID());
RecordReader<LongWritable, Text> reader = myInputFormat.createRecordReader(splits.get(1), context);
reader.initialize(splits.get(1), context);
for (; number of expected value;) {
assertTrue(reader.nextKeyValue());
// verify key and value
assertEquals(expectedLong, reader.getCurrentKey());
}