I need to make some operations on bitmaps in android, such as chanding pixel colors, transparency, painting another bitmap on the first one with transparency, zooming, croping, applying masks and so on. Now I make it with java and it is really slow. It take about 5 seconds to compute a 600x600 pixels image on nexus 4.
What technology will be suitable for this operations?
I tried library GPUImage that uses OpenGL ES 2.0, but I faced a problem when trying to apply a mask to an image, mask size is 600x600 as the original image, so I should pass an array of 1440000 color values, and the GLSL language doesnt support such big arrays. 360000 of vec4 values is too large for it too.
May be I can pass a whole image as a texture2d object, but I cant find how to do it. Cold someone please give me a tutorial?
The second option is renderscript. It is not so suitable because I want phones with android 2.3 has fast bitmap operations, but all in all improving speed on 3.0+ devices will be a good thing. The problem with it was how to pass it data of second bitmap - 360000 of float4 values or a bitmap itself. I coudnt find information about it too, so I would be thankful if someone give me an advice or tutorial.
The third option is using NDK. But I dont know will it be fast enough and again cant find good information to start with ndk in general and image processing with ndk in particular. So I again need an advice or tutorial.
So, all in all, please tell me what other ways of fast image processing are there and please give me some advices or tutorials on this 3 methods.
And what is the best way to make operations on images really fast?
If you find GLES suitable, divide the image into small tiles, and operate on one tile at a time. (Some drivers work this way.)
Related
I tried searching in a ton of places about doing this, with no results. I did read that the only (as far as I know) way to obtain image frames was to use a ImageReader, which gives me a Image to work with. However, a lot of work must be done before I have a nice enough image (converting Image to byte array, then converting between formats - YUV_420_888 to ARGB_8888 - using RenderScript, then turning it into a Bitmap and rotating it manually - or running the application on landscape mode). By this point a lot of processing is made, and I haven't even started the actual processing yet (I plan on running some native code on it). Additionally, I tried to lower the resolution, with no success, and there is a significant delay when drawing on the surface.
Is there a better approach to this? Any help would be greatly appreciated.
Im not sure what exactly you are doing with the images, but a lot of times only a grayscale image is actually needed (again depending on your exact goal) If your camera outputs YUV, the grayscale information is in the Y channel. The nice thing,is you don't need to convert to numerous colorspaces and working with only one layer (as opposed to three) decreases the size of your data set greatly.
If you need color images then this wouldn't help
I am trying to write a libgdx livewallpaper (OpenGL ES 2.0) which will display a unique background image (non splittable into sprites).
I want to target tablets, so I need to somehow be able to display at least 1280x800 background image on top of which a lot more action will also happen, so I need it to render as fast as possible.
Now I have only basic knowledge both about libgdx and about opengl es, so I do not know what is the best way to approach this.
By googling I found some options:
split texture into smaller textures. It seems like GL_MAX_TEXTURE_SIZE on most devices is at least 1024x1024, but I do not want to hit max, so maybe I can use 512x512, but wouldn't that mean drawing a lot of tiles, rebinding many textures on every frame => low performance?
libgdx has GraphicsTileMaps which seems to be the tool to automate drawing tiles. But it also has support for many features (mapping info to tiles) that I do not need, maybe it would be better to use splitting by hand?
Again, the main point here is performance for me - because drawing background is expected to be the most basic thing, more animation will be on top of it!
And with tablet screen growing in size I expect soon I'll need to be able to comfortably render even bigger image sizes :)
Any advice is greatly appreciated! :)
Many tablets (and some celphones) support 2048 textures. Drawing it in one piece will be the fastest option. If you still need to be 100% sure, you can divide your background into 2 pieces whenever GL_MAX_TEXTURE happens to be smaller (640x400).
'Future' tables will surely support bigger textures, so don't worry so much about it.
For the actual drawing just create a libgdx mesh which uses VBOs whenever possible! ;)
Two things you dindn't mention will be very important to the performance. The texture filter (GL_NEAREST is the ugliest if you don't do a pixel perfect mapping, but the fastest), and the texture format (RGBA_8888 would be the best and slowest, you can downgrade it until it suits your needs - At least you can remove alpha, can't you?).
You can also research on compressed formats which will reduce the fillrate considerably!
I suggest you start coding something, and then tune the performance up. This particular problem you have is not that hard to optimize later.
I am currently porting an application from iOS into Android and I have ran into some difficulties when it comes to image processing.
I have a filter class that is comprised of ImageOverlays and ColorOverlays which are applied in a specific order to a given base Bitmap. Each ColorOverlays has an RGB color value, a BlendModeId, and an alpha value. Each ImageOverlay has an image Bitmap, a BlendModeId, and an alpha/intensity value.
My main problem is that I need to support the following blend modes taken from iOS:
CGBlendModeNormal
CGBlendModeMultiply
CGBlendModeScreen
CGBlendModeOverlay
CGBlendModeDarken
CGBlendModeLighten
CGBlendModeColorDodge
Some of these have corresponding PorterDuff.Mode types in Android while others do not. What's worse, some of the modes that do exist were introduced in recent versions of Android and I need to run on API level 8.
Trying to build the modes from scratch is extremely inefficient.
Additionally, even with the modes that do exist in API8, I was unable to find methods that blend 2 images but that allow you to specify the intensity of the mask (the alpha value from ImageOverlay). Similarly with ColorOverlays.
The iOS functions I am trying to replicate in Android are
CGContextSetBlendMode(...)
CGContextSetFillColorWithColor(...)
CGContextFillRect(...) - This one is easy
CGContextSetAlpha(...)
I have started looking at small third party libraries that support these blend modes and alpha operations. The most promising one was poelocesar's lib-magick which is supposedly a port of ImageMagick.
While lib-magick did offer most of the desired blend modes (called CompositeOperator) I was unable to find a way to set intensity values or to do a color fill with a blend mode.
I'm sure somebody has had this problem before. Any help would be appreciated. BTW, Project specifications forbid me from going into OpenGLES.
Even though I helped you via e-mail, I thought I'd post to your question too in case someone wanted some more explanation :-)
2.2 is API level 8, which supports the "libjnigraphics" library in the
NDK, which gives you access to the pixel buffer for bitmap objects.
You can do these blends manually - they are pretty simple math
calculations and can be done really quickly.
Check out this site for Android JNI bitmap information.
It's really simple, just create a JNI method blend() with any
parameters you need (either the color values or possibly another bitmap object to blend together), lock the pixel buffer for that bitmap, do the
calculation needed, and unlock the bitmap. Link
Care needs to be taken on the format of the bitmap in memory, though,
as the shifting/calculation for 565 will be different than 8888. Keep that in mind if it doesn't look exactly correct!
It turned out that implementing it in the jni wasn't nearly as painful as previously expected. The following link had all the details.
How does photoshop blend two images together?
I was hoping someone could tell me why it is my Tesseract has trouble recognizing some images with digits, and if there is something i can do about it.
Everything is working according to test, and since it is only digits i need, i thought i could manage with the english pattern untill i had to start with the 7segmented display aswell.
Though i am having a lot of trouble with the appended images, i'd like to know if i should start working on my own recognition algorithms or if I could do my own datasets for Tesseract and then it would work, does anyone know where the limitation lies with Tesseract?
things tried:
tried to set psm to one_line, one_word, one_char(and chop up the picture).
With one_line and one_word there was no significant change.
with one_char it did recognize a bit better, but sometimes, due to big spacing it attached an extra number to it, which then screwed it up, if you look at the attached image then it resulted in 04.
I have also tried to do the binarization myself, this resulted in poorer recognition and was very rescource consuming.
I have tried to invert the pictures, this makes no difference at all for tesseract.
I have attached the pictures i'd need, among others, to be processed.
Explaination about the images:
is a image that the tesseract has no trouble recognizing, though it has been made in word for the conveniences of building an app around a working image.
is real life image matching the image_seven. But it cannot recognize this.
is another image i'd like it to recognize, and yes i know it cant be skrewed, and i did unskrew(think skrew is the term here=="straighting") it when testing.
I know of some options that might help you:
Add extra space between image border and text. Tesseract would work awful if text in the image is positioned at the edge.
Duplicate your image. For example, if you're performing OCR on a word 'foobar', clone the image and send 'foobar foobar foobar foobar foobar' to tesseract, results would be better.
Google for font training and image binarization for tesseract.
Keep in mind, that built-in camera in mobile devices mostly produce low quality images (blured, noised, skewed etc.) OCR itself is a resource comsuming process and if you add a worthy image preprocessing to that, low-end and mid mobile devices (which are likely to have android) could face unexpectedly slow performance or even lack of resources. That's OK for free/study projects, but if you're planning a commercial app - consider using a better SDK.
Have a look at this question for details: OCR for android
Tesseract doesn't do segmentation for you. Tesseract will do a thresholding of the image prior to the actual tesseract algo. After thresholding, there may be some edges, artefacts that remain in the image.
Try to manually modify your images to black and white colors and see what tesseract returns as output.
Try to threshold (automatically) your images and see what tesseract returns as output. The output of thresholding may be too bad causing tesseract to give bad output.
Your 4th image will probably fail due to thresholding (you have 3 colors: black background, greyish background and white letters) and the threshold may be between (black background, greyish background).
Generally Tesseract wants nice black and white images. Preprocessing of your images may be needed for better results.
For your first image (with the result "04"), try to see the box result (char + coordinates of box that contains the recognized char). The "0" may be a small artefact - like a 4 by 4 blob of pixels.
You may give javaocr a try ( http://sourceforge.net/projects/javaocr/ , yes, I'm developer )
Therre is no offocial release though, and you will have to look for sources ( good news: there is working android sample including sampler, offline trainer and recognizer application )
If you only one font, you can get pretty good results with it (I reached up to recognition rates 99.96 on digits of the same font)
PS: it is pure java and uses invariant moments to perform matching ( so no problems with scaling and rotation ) . There is also pretty effective binarisation.
See it in action:
https://play.google.com/store/apps/details?id=de.pribluda.android.ocrcall&feature=search_result#?t=W251bGwsMSwxLDEsImRlLnByaWJsdWRhLmFuZHJvaWQub2NyY2FsbCJd
In my view I have a simple ARGB drawable that takes about 2ms to draw but I can draw the same file as a bitmap in under 0.5ms (just some quick code, I can't really consider it an option). What are the best ways to optimize the drawing speed of a drawable?
It will depend on the number of drawables and how many times each gets drawn. For a small number, use canvas (an exact number will also depend on the device) I would suggest using Canvas as it's a nice higher level approach to drawing.
If you want to crank out a lot of images (think hundreds), I would suggest creating a GLSurfaceView and using openGL to render your images using VBOs tailored to your app. I would also recommend using a texture sheet if you go down this route since you'll get a huge increase in performance at the cost of code complexity.
But this will also depend on that type of app. My background is in game development so I use openGL exclusively for better performance. for a simple app (something along the lines of androidify) Canvas should be fine. If you want a simple tutorial for openGL, I suggest visiting Bergman's series of posts on the topic (google should give you a link for that). It is a nice intro to openGL.