I created an application for scanning text from an image and write it on a textview ,it worked successfully for single column of data,But in case of multiple columns it read columns randomly and not printing the same way as a table view that the original image appears. I used google vision api and parse the text into a SparseArray of type textblock(SparseArray<Textblock>).
Output screenshot of the scanned image:
Frame frame=new Frame.Builder().setBitmap(bitmap).build();
SparseArray<TextBlock> textBlocks = recognizer.detect(frame);
String blocks = "";
String lines = "";
String words = "";
for (int index = 0; index < textBlocks.size(); index++) {
//extract scanned text blocks here
TextBlock tBlock = textBlocks.valueAt(index);
blocks = blocks + tBlock.getValue() + "\n" + "\n";
for (Text line : tBlock.getComponents()) {
//extract scanned text lines here
lines = lines + line.getValue() + "\n";
for (Text element : line.getComponents()) {
//extract scanned text words here
words = words + element.getValue() + ", ";
}
}
}
if (textBlocks.size() == 0) {
etresult.setText("Scan Failed: Found nothing to scan");
} else {
etresult.setText(etresult.getText() + "Blocks: " + "\n");
etresult.setText(etresult.getText() + blocks + "\n");
saveToInternalStorage(bitmap);
}
After going through above code I can see that the OCR is supposed to scan the image and detect the text not the text alignment like tables and its columns. But you can
recognise the alignment by using Bounding boxes which gives top-left,top-right,bottom-left,bottom-right corordinates. Please go through Google cloud vision api documentation. https://cloud.google.com/vision/docs/ocr
Related
I have try already to convert unicode to emoji but at a time only one emoji set. i want display in textview multiple emoji .
my problem is i want to display text with multiple emoji on textview dynamically.
for example : String str = "Happy" + unicode + "Birthday" + unicode + "ComingSoon" + unicode + "Dear" + unicode + unicode;
according to above string i want display multiple emoji with text on textview.
private static String escapeNonAscii(String str) {
StringBuilder mStr = new StringBuilder();
for(int i=0; i<str.length(); i++) {
int cp = Character.codePointAt(str, i);
int charCount = Character.charCount(cp);
if (charCount > 1) {
i += charCount - 1; // 2.
if (i >= str.length()) {
throw new IllegalArgumentException("truncated unexpectedly");
}
}
if (cp < 128) {
mStr .appendCodePoint(cp);
} else {
mStr .append(String.format("\\u%x", cp));
}
}
return mStr.toString();
with above code noot display emojis...
I started out by following the Text API tutorial to detect TextBlocks, which worked fine. But I now want to detect text lines, and encountered a problem.
// TODO: Create the TextRecognizer
TextRecognizer textRecognizer = new TextRecognizer.Builder(context).build();
// TODO: Set the TextRecognizer's Processor.
textRecognizer.setProcessor(new OcrDetectorProcessor(mGraphicOverlay));
textRecognizer.setProcessor can only use TextBlock.
Is there any way for it to detect lines?
Click Here, to read full code. Hopefully, it will help you.
Bitmap bitmap = decodeBitmapUri(this, imageUri);
if (detector.isOperational() && bitmap != null) {
Frame frame = new Frame.Builder().setBitmap(bitmap).build();
SparseArray<TextBlock> textBlocks = detector.detect(frame);
String blocks = "";
String lines = "";
String words = "";
for (int index = 0; index < textBlocks.size(); index++) {
//extract scanned text blocks here
TextBlock tBlock = textBlocks.valueAt(index);
blocks = blocks + tBlock.getValue() + "\n" + "\n";
for (Text line : tBlock.getComponents()) {
//extract scanned text lines here
lines = lines + line.getValue() + "\n";
for (Text element : line.getComponents()) {
//extract scanned text words here
words = words + element.getValue() + ", ";
}
}
use this one:
List<Line> lines = (List<Line>) text.getComponents();
for(Line elements : lines) {
Log.i("current lines ", ": " + elements.getValue());
}
This tutorial (https://codelabs.developers.google.com/codelabs/mobile-vision-ocr/#6) says that "The engine puts all the text it recognizes in a TextBlock into one complete sentence, even if it sees the sentence broken over multiple lines."
"You can get the Lines from a TextBlock by calling getComponents, and then you can iterate over each line to get the location and values of the text within it. This lets you put the text in the place it actually appears."
// Break the text into multiple lines and draw each one according to its own bounding box.
List<? extends Text> textComponents = mText.getComponents();
for(Text currentText : textComponents) {
float left = translateX(currentText.getBoundingBox().left);
float bottom = translateY(currentText.getBoundingBox().bottom);
canvas.drawText(currentText.getValue(), left, bottom, sTextPaint);
}
The solution I came up with, going from Pedro Madeira's answer, was this:
List<? extends Text> textComponents = mText.getComponents();
for (Text currentText : textComponents) {
RectF rect = new RectF(currentText.getBoundingBox());
rect.left = translateX(rect.left);
rect.top = translateY(rect.top);
rect.right = translateX(rect.right);
rect.bottom = translateY(rect.bottom);
canvas.drawRect(rect, sRectPaint);
I have 4 textviews which take their values from dropdown list (spinner) selected at previous screen.
There can be either 2 or 4 numbers/letters as result of this selection.
The first position will always be a number and the second position will always be a letter. The third position can be a number or blank and the fourth position can be a letter or blank.
If position 3 and position 4 are blank then I need to make them equal to positions 1 & 2 respectively.
String myGrade = intent.getStringExtra("parameter_name_grade");
// above takes value of 'myGrade' from spinner selection at previous screen
String mDisplayGradeNumberEff = (" " + myGrade.charAt(0));
TextView displayGradeNumberEff = (TextView) findViewById(R.id.gradeNumberEffTV);
displayGradeNumberEff.setText(mDisplayGradeNumberEff);
String mDisplayGradeLetterEff = (" " + myGrade.charAt(1));
TextView displayGradeLetterEff = (TextView) findViewById(R.id.gradeLetterEffTV);
displayGradeLetterEff.setText(mDisplayGradeLetterEff);
// above works correctly
// from here down only works when a character is present in both positions
// if positions 3(2) and 4(3) are empty app stops running.
String mDisplayGradeNumberDia = (" " + myGrade.charAt(2));
if (mDisplayGradeNumberDia.isEmpty()) {
mDisplayGradeNumberDia = mDisplayGradeNumberEff;
}
TextView displayGradeNumberDia = (TextView) findViewById(R.id.gradeNumberDiaTV);
displayGradeNumberDia.setText(mDisplayGradeNumberDia);
String mDisplayGradeLetterDia = (" " + myGrade.charAt(3));
if (mDisplayGradeLetterDia.isEmpty()) {
mDisplayGradeLetterDia = mDisplayGradeLetterEff;
}
TextView displayGradeLetterDia = (TextView) findViewById(R.id.gradeLetterDiaTV);
displayGradeLetterDia.setText(mDisplayGradeLetterDia);
}
I Guess you have a array out of bounds exception, please provide Logcat....
Check if "myGrade" has 3/4 Characters, if it does not you can't read them with charAt(3)...
You can check the length of the String with "myGrade.length()"
When I asked this question I was fairly new to the site and didn't understand that I should post back the solution for future reference. Solution below worked so thanks to rocket for your help and sorry for the delay!
int myGradeLength = mGrade.length();
if (myGradeLength != 4) {
mDisplayGradeNumberEff = ("" + mGrade.charAt(0));
mDisplayGradeLetterEff = ("" + mGrade.charAt(1));
mDisplayGradeNumberDia = ("" + mGrade.charAt(0));
mDisplayGradeLetterDia = ("" + mGrade.charAt(1));
} else {
mDisplayGradeNumberEff = ("" + mGrade.charAt(0));
mDisplayGradeLetterEff = ("" + mGrade.charAt(1));
mDisplayGradeNumberDia = ("" + mGrade.charAt(2));
mDisplayGradeLetterDia = ("" + mGrade.charAt(3));
}
I have long string that at some part has
some text + "PHOTO;ENCODING=BASE64;TYPE=JPEG:" + some characters that generate randomly + /r/n...
I am wondering how can I delete part from
"PHOTO;ENCODING=BASE64;TYPE=JPEG:" untill /r/n
so I will be left only with
some text + /r/n ?
my code so far:
if (string.contains("PHOTO;ENCODING=BASE64;TYPE=JPEG:") {
string = string.replace("PHOTO;ENCODING=BASE64;TYPE=JPEG:", "");
}
but this obviously would not replace my random generated chars, only "PHOTO;ENCODING=BASE64;TYPE=JPEG:".
How do I "loop through" string from "PHOTO;ENCODING=BASE64;TYPE=JPEG:" untill /r/n ?
final String input = "some text + PHOTO;ENCODING=BASE64;TYPE=JPEG: + some characters that generate randomly + /r/n"
final int index = input.indexOf("PHOTO;ENCODING=BASE64;TYPE=JPEG:");
if (index != -1)
{
final String result = input.subString(0, index) + System.getProperty("line.separator")
}
why dont you try following
1) Get the index of "PHOTO;ENCODING=BASE64;TYPE=JPEG:". and call it idx
2)If idx != -1 then take substring of original string using str.subString(0,idx) and call it newStr
3)return newStr+(str.endsWith("\r\n")?"\r\n":"")
I am having a string(number) with special characters. I want to search for a sub-string(comprising of digits only) & also I want to detect the starting index & ending index of matching sub-string in the string.
For example: main string: (+91)-1231212 1231
Sub-string to search: 1212
Currently I am using the following code to do this but in place of 1212,it searched for 12312. For other cases, it works fine.
String sss0 = "1212";
String sss1 = "(+91)-1231212 1231";
sss0 = sss0.replaceAll("[^\\d]","");
System.out.println("*************************"+sss0);
String ptn = "" + sss0.charAt(0);
for(int jj=0; jj<sss0.length()-1; jj++){
ptn += "[^" + sss0.charAt(jj) + sss0.charAt(jj+1) + "]*?" + sss0.charAt(jj+1);
}
System.out.println("ptn: " + ptn);
Pattern p300 = Pattern.compile(ptn);
Matcher m300 = p300.matcher(sss1);
if(m300.find()){
System.out.println("start, stop: " + m300.start() + "," + (m300.end()-1 ));
System.out.println("substring: " + sss1.substring(m300.start(), m300.end()));
}
Please help me. Thanks in advance.
Try this :
int start = sss1.indexOf(sss0);
if(start != -1) {
System.out.println("Start : " + start);
System.out.println("End : " + start.length()); //maybe add +1 here depending on what you mean by end index.
}
You can also put this in a loop to find all occurences of the substring.
pseudocode:
pattern = ""
foreach char c in sss0:
pattern += c + "[^0-9]*"
found_substring = match(pattern, sss1)
the idea being to intersperse the literal characters you're looking for with the pattern that you're willing to skip over.