TextRecognizer can only detect TextBlocks - android

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);

Related

I am trying to display text and multiple emoji from unicode in tetxview dynamically

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...

Text alignment issue with OCR

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

I want to highlight the single word of the ArrayList

I want to give background color to the text that I receive from a List. At the moment I can get highlighted all the words, but I would like to exclude the spaces between the words
Initially I tried was to use a Pattern Matcher Regex solution so to exclude the double spaces, I was appending to the List. Then I realised that this solution was not the best because I could not exclude the spaces. So I decided to use a SpannableStringBuilder and append the items inside a for loop. But does not work I get only the first word highlighted and not all the single words( separated by a blank(not coloured)word
val spannable = SpannableStringBuilder()
val span = BackgroundColorSpan(yellowColor))
listOfUsers.forEach {
val string = it.users
spannable.append(string)
spannable.setSpan(span, 0, string.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
textValue.text = spannable
I expect to see not only the first word, but the single words updated.
Please notice that I am aware that the problem is in setSpan where I put as start 0 but I do no know how to make start working so to highlight the right initial string[I] character
You can create method that returns Spannable like below:
public Spanned formatAutoSuggestText(final String autoSuggestText) {
if (autoSuggestText == null) {
return Html.fromHtml("");
}
try {
String modifiedAutoSuggestText= "" ;
final String searchText = "Text to highlight";
final Pattern pattern = Pattern.compile(StringUtils.INSENSITIVE_CASE + searchText);
final Matcher matcher = pattern.matcher(autoSuggestText);
int end = 0;
while (matcher.find()) {
final String subStringMatchFound = autoSuggestText.substring(end, matcher.end());
final String stringToBeReplaced = autoSuggestText.substring(matcher.start(), matcher.end());
final String stringToReplace = "<b><font color='" + mContext.getResources().getColor(R.color.search_autosuggest_highlighted_text) + "'>" +matcher.group()+ "</font></b>";
modifiedAutoSuggestText += subStringMatchFound.replace(stringToBeReplaced,stringToReplace);
end = matcher.end();
}
modifiedAutoSuggestText += autoSuggestText.substring(end);
return Html.fromHtml(modifiedAutoSuggestText);
}
catch (final Exception e){
return Html.fromHtml(autoSuggestText);
}
}
The code is in Java. you can change this based on your needs.
You can write regex like below to match multiple spaces. You can replace as well.
fun regexTest(){
val words = listOf("Hello", "Hello World1", "Hello World2",
"Hello World3", "Hello World4 ")
val pattern = "\\s+".toRegex()
words.forEach { word ->
if (pattern.containsMatchIn(word)) {
println("match ---> $word")
var temWord = word.replace("\\s+"," ")
}
}
var result:ArrayList<String> = ArrayList()
for (s in words) {
result.add(s.replace(pattern, " "))
}
for(wordToPrint in result){
println("replaced ---> $wordToPrint")
}
}
Below is the output for the above program:
match ---> Hello World1
match ---> Hello World2
match ---> Hello World3
match ---> Hello World4
replaced ---> Hello
replaced ---> Hello World1
replaced ---> Hello World2
replaced ---> Hello World3
replaced ---> Hello World4
You can modify the regex according to your needs.

Prevent line-break in TextView

In my Android app I have a text view that displays text containing special characters. The TextView somehow automatically breaks strings at the characters '/' and '-'.
For example, the string "aaaaaaa/bbb-ccccc/ddd" is displayed as
aaaaaaa/
bbb-
ccccc/
ddd
However, I would like to display it without any linebreaks except the one at the boundaries of the view, i.e., like this:
aaaaaaa/bb
bb-ccccc/d
dd
Is there any way to deactivate the automatic line-breaks or to escape these characters? I already tried escaping with \uFEFF without success.
Keep your textview attribute
android:layout_width="wrap_content"
android:layout_height="wrap_content"
Define Your string in string.xml
<string name="Username"> aaaaaaa\/bb\nbb\-ccccc\/d\ndd</string>
Maybe this is a solution: https://stackoverflow.com/a/22337074/3472905
I've added the slash as mentioned:
public class WordBreakTransformationMethod extends ReplacementTransformationMethod {
private static WordBreakTransformationMethod instance;
private WordBreakTransformationMethod() {}
public static WordBreakTransformationMethod getInstance() {
if (instance == null) {
instance = new WordBreakTransformationMethod();
}
return instance;
}
private static char[] dash = new char[]{'-', '\u2011'};
private static char[] space = new char[]{' ', '\u00A0'};
private static char[] slash = new char[]{'/', '\u2215'};
private static char[] original = new char[]{dash[0], space[0], slash[0]};
private static char[] replacement = new char[]{dash[1], space[1], slash[1]};
#Override
protected char[] getOriginal() {
return original;
}
#Override
protected char[] getReplacement() {
return replacement;
}
}
Its is a new thing in Android 6.
Try adding this to your TextView xml layout
android:hyphenationFrequency="none"
Android TextView follows the standard Unicode line break algorithm: http://www.unicode.org/reports/tr14/tr14-45.html
Excerpt: / Prevent a break before, and allow a break after
You can work around this by placing the 'word joiner' character (U+2060) after the slashes.
Example from strings.xml:
aaaaaaa/\u2060bbb-ccccc/\u2060ddd
You can also try using android:breakStrategy="balanced" to keep the lines roughly the same length.
this is work's for me in kotlin
object WordBreakTransformationMethod : ReplacementTransformationMethod() {
private val dash = charArrayOf('-', '\u2011')
private val space = charArrayOf(' ', '\u00A0')
private val slash = charArrayOf('/', '\u2215')
private val original = charArrayOf(dash[0], space[0], slash[0])
private val replacement = charArrayOf(dash[1], space[1], slash[1])
override fun getOriginal() = original
override fun getReplacement() = replacement
}
//tv_text is TextView
tv_text.apply {
transformationMethod = WordBreakTransformationMethod
text = item.text
}
There no ready solution and no such thing as "wrap text by letters in TextView" the only way to do it in a good way is to extend TextView and modify Paint's breakText(String text, boolean measureForwards, float maxWidth, float[] measuredWidth) function.
Also, you can calculate TextView size in pixels, calculate width of one letter in pixels, then find number of letters (X) that will fit in one line and then insert linebreak after each X letters
you probably can use the Lines attribute or its counter-part method setLines(int)
I have tested the following code. You can even convert it into a function:
String specialString = "a/b/-c/d-d";
String[] specialArray = specialString.split("/");
String str = "";
for(int i = 0; i < specialArray.length - 1; i++){
str = str + specialArray[i] + Character.toString((char) 47);
}
str = str + specialArray[specialArray.length - 1];
specialArray = str.split("-");
str = "";
for(int i = 0; i < specialArray.length - 1; i++){
str = str + specialArray[i] + Character.toString((char) 45);
}
str = str + specialArray[specialArray.length - 1];
textView.setText(str);
Now the text does not escape
You can calculate the size of a text this way:
String text = "This is my text";
Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setTextSize(14.0f);
Rect bounds = new Rect();
textPaint.getTextBounds(text, 0, text.length(), bounds);
bounds.width() // width in pixels
bounds.height() // height in pixels
Based on these values you could break up the text in pieces and insert newline characters.

To change the color for each line in android

Hi,
I used this code:
String displayText = "";
try {
InputStream fileStream = getResources().openRawResource(
R.raw.t);
int fileLen = fileStream.available();
// Read the entire resource into a local byte buffer.
byte[] fileBuffer = new byte[fileLen];
fileStream.read(fileBuffer);
fileStream.close();
displayText = new String(fileBuffer);
} catch (IOException e) {
// exception handling
}
TextView tv=(TextView) findViewById(R.id.textView1);
tv.setText(displayText);
}
It's for displaying a text file.
I want to change the color on each line ( and change the color of a line in between lines)
What should I do?
I'm sorry for bad speak english
I suggest you use html to set the colors in your textview. A small example that swaps between 2 colors:
String textcontent = "";
String[] lines;
//something like "lines = displayText.split("\n")" or however you stored line returns
for (int i = 0; i < lines.length; i++) {
//odd line numbers are red, the even ones green
textcontent += "<font color=\"" + (i%2==0?"red":"green") + "\">" + lines[i] + "</font><br/>";
}
TextView tv=(TextView) findViewById(R.id.textView1);
tv.setText(Html.fromHtml(textcontent));
I hope this helped, otherwise feel free to ask for more...

Categories

Resources