Android OCR tesseract: using data from Pixa objects to display bounding boxes - java

I am currently playing around with OCR on android. Therefore I wrote a small app with a Camera preview and now I am feeding tessearact tools (tess-two) images from my onPreviewFrame method. Now I want to display the bounding rectacles from the OCR on my Camera Preview. The TessBaseAPI provides methods that return character/word bouding boxes. The type of the returned object is Pixa, as in the leptonica library provided with tess-two.
So my Question is: How do i get usable coordinates which I can use to draw the bounding boxes on my camera preview from the Pixa objects returned by getCharacters() or getWords() from the TessBaseAPI?
GetCharacters() and getWords() in the BaseAPI
leptonicas Pixa class
Important:
Because the previews only supported image-format is YUV N21 and as far from what I have read the tess-API requires ARGB_8888 Bitmaps I have the following workaround in my onPreviewFrame method right before i feed the bitmap to the TessAPI: (I am also rotating by 90 degrees clockwise because I am using the camera in portrait orientation, but the cameras preview frames come in landscape)
//byte[] bmpdata <- the image in a byte array (NV21 Imageformat) in onPreviewFrame
YuvImage yuvimage = new YuvImage(bmpdata,ImageFormat.NV21,width,height,null);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
Rect rect = new Rect(0, 0, width, height);
yuvimage.compressToJpeg(rect, 100, outStream);
Bitmap bmp = BitmapFactory.decodeByteArray(outStream.toByteArray(),0,outStream.size());
Matrix mtx = new Matrix();
mtx.preRotate(90);
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mtx, false);
bmp = bmp.copy(Bitmap.Config.ARGB_8888, true);
TessTBaseApi.setImage(bmp);
So basically, I compress the NV21 byte[] I got from the camera into a YuvImage, then into a jpeg, and from there into a bitmap. I searched the web alot for the solution on how to get bitmap/jpeg from the NV21 array and this was the easiest i found. This bitmap will be fed to tesseract tools OCR. This brings me to my second question:
How, after these compressions and 90 degree rotation, do I locate where I have to draw the boxes on screen? (relative to before the compressions and the rotation)
This might not be the best or even a good way to supply the OCR with live frames, I appreciate very much comments, other solutions or suggestions of ways of optimzation.
I started this Project two days ago and am a very beginner in programming for android and ocr. During these two days this page helped me alot and answered questions I had so far very well, so thanks for that and thank you in advance for helping me with my current problem. If you would like to see more code or have questions, I will supply and be glad to answer anything I can.
Greetings
You can browse trough the whole API sourcecode on github trough the Pixa class and GetCharacters() links, cant insert more hyperlinks.

TessTBaseApi.getWords().getBoxRects() will return an ArrayList of bounding box Rects with coordinates relative to your bmp bitmap.

Related

How to convert DAE to PNG programmatically without rendering?

At present I am rendering a DAE using a c++ based graphics engine, and programmatically taking a screenshot to get the PNG image as if the camera is viewing from above (looking directly down). This is quite tedious.
Since I do not need to actually look at the models on screen, is it possible to do the same programmatically without rendering using java ?
At present, it is easy to convert between other 2d formats such as PNG to jpeg using buffered image:
BufferedImage newImage = new BufferedImage( pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_INT_RGB);
newImage.createGraphics().drawImage( pngImage, 0, 0, Color.BLACK, null);
Is there a similar way to load the DAE and take the equivalent of a screenshot by specifying the camera position, angle and distance as input coordinates ?

Android Drawing Performance - canvas.drawRect vs Bitmap Drawing

I am writing a particle based game that is mainly built by drawing lots of colored shapes.
Question 1)
For most of the enemy units I am drawing 4 layered rectangles by setting the paint and then drawing the rectangle through the canvas.
I was wondering if it is better to draw using bitmaps, or to draw using the canvas drawing tools? I could easily make a single image of the enemy unit that I wish to draw.
Question 2)
For the images that I have to draw to the screen, I was wondering how I need to load them?
Right now I have tons of .png images loaded like this:
direction1 = BitmapFactory.decodeStream(assetMgr.open("direction1.png"));
I've read that RGB565 is the fasted image type to draw to the screen. Microsoft Paint has some saving options, but for the most part programs only save as a bitmap, not a type of bitmap. If I was to start using that new format would I:
Make new images and use the same loading code.
Use the same images and add something like Bitmap bmp =
Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); to
convert from the initial loaded format to the RGB565 format.
Make new images and change my loading code.
Thanks for any help! It is very appreciated.
None. It is always better to use OpenGL and the only downside is
that it requires more energy from a battery because it's hardware
accelerated.
RGB565 means that image uses 16 bits so that's the
option you should look for. Don't convert anything, just create them
in the format you will be using.
If the Bitmap aren't moving frame-by-frame, you should try to reduce invalidate() method call. The canvas should only be re-drawn when changes are made and should be updated.

Is it possible to add transparency to jpg in Java and Android

I want to load some images to the cloud, but I want to add some protections when someone views the photos and saves the images; they will not see anything because of the transparency.
would the code be common for Java and Android? I would like to prototype it in Java first.
I have found some code that combines two files. One file is my main file the other is a transparent file. The combined file does not have a transparent overlay.
Do I need to use an image drawing order?
http://www.developer.nokia.com/document/Java_Developers_Library_v2/GUID-D3E35E6F-0C45-48ED-B09D-F716E14C1C02/javax/microedition/amms/control/imageeffect/OverlayControl.html
BufferedImage image = ImageIO.read(new File("rose.jpg"));
BufferedImage overlay = ImageIO.read(new File("myimg1.gif"));
// create the new image, canvas size is the max. of both image sizes
int w = Math.max(image.getWidth(), overlay.getWidth());
int h = Math.max(image.getHeight(), overlay.getHeight());
BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
// paint both images, preserving the alpha channels
Graphics g = combined.getGraphics();
g.drawImage(image, 0, 0, null);
g.drawImage(overlay, 0, 0, null);
// Save as new image
ImageIO.write(combined, "PNG", new File("combined.png"));
This won't work. If they can see the image, they can copy it, one way or another. A solution to consider is providing watermarked thumbnails at no charge, then only offering the full resolution image for a fee. However, they can still copy the full resolution image once they pay.
You can actually put a trans image as an overlay to the orginial image, that will
Protect from download, I think this is usually done by the server side aka your cloud
I know from some websites that they use some kind of an overlay such as yours
And the browser can't see the image below so you can't download.
I actually didn't understand how you implementing this - the image is opened in the browser?
Just a wild though, you can also cut the image into pieces like a jigsaw puzzle
The device won't have problems connecting it togther but when you download you'll
Download only "one piece of the puzzle" :-P

Lossless image rotation

I'm currently trying to implement a rotate feature in my app wich is playing with images.
The feature would allow the user to rotate an image -90 and +90 degree (switching landscape/portrait mode)
Here is my code :
public Bitmap rotateRight(Bitmap bm) {
Matrix matrix = new Matrix();
matrix.postRotate((float)90);
Bitmap nbm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
nbm.setDensity(bm.getDensity());
return nbm;
}
After that, i save the image to the filesystem.
This work perfectly but the problem appears if i try to rotate 5 or 6 times the same image. The image quality will decrease and I will finally have a very ugly image to show...
Could you help me ?
Thank you in advance !
First: the last parameter in createBitmap() is whether to filter the resulting bitmap. As it is set to true, every time you perform this action your bitmap will become slightly more "blurred". As you do not change the size of the Bitmap, you might want to turn this off.
Secondly: make sure you save the image as a lossless format, such as PNG. If you save as JPG or another lossy format you will always reduce quality with each save, even if you set quality parameters to highest.

Correct way to convert between Bitmap and Mat in OpenCV on Android?

I'm currently trying to migrate a bit of legacy code from iPhone to Android. This code uses the OpenCV library to do some image processing.
And I cannot understand how to do the conversion between Mat and Android Bitmap classes.
This code shows a very simplified example which loads a bitmap into a Mat, then converts it back to Bitmap. The resulting image looks weird - it's filled with blue and white pixels. And the original is a normal PNG image...
Mat img = Utils.loadResource(context, resId);
Bitmap tmp = Bitmap.createBitmap(img.rows(), img.cols(),
Bitmap.Config.ARGB_8888);
Utils.matToBitmap(img, tmp);
Currently matToBitmap is a bit buggy, I've read they intend to fix it in a future release.
I can show it how I worked around it for a color image:
mMat = Utils.loadResource(this, resId, Highgui.CV_LOAD_IMAGE_COLOR);
Imgproc.cvtColor(mMat, result, Imgproc.COLOR_RGB2BGRA);
bmp = Bitmap.createBitmap(result.cols(), result.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(result, bmp);
mImageView.setImageBitmap(bmp);
Basically i perform that space color conversion first or like you said the result will be a weird blend of random colors.
Answer if it works, I think it does.

Categories

Resources