Android ZXing image processing - android

I have to scan a Data Matrix written on something like this.
The code is white/light gray but the background reflects different colors, depending on the position of the camera(angle), light.
Where would be the right place to edit the image captured in Android Zxing?
Is there any possible adjustment to make the image black on white before processing?
Any idea would be great.

Bitmap bm = Bitmap.createBitmap(500, 500, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bm);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
int xo = (w-500)/2;
int yo = (h-500)/2;
c.drawBitmap(bmp, -xo, -yo, paint);
bmp.recycle();

Also have a look at this class:
http://zxing.org/w/docs/javadoc/com/google/zxing/common/HybridBinarizer.html
Maybe you are using by default the GlobalHistogramBinarizer, which is faster but doesn't work so good with gradients.

It seems that you need some image processing before recognition. Previous answer suggest histogram bianrizer, which is sensitive to background intensity changes. Sauvola filter is known to have good tolerance to background changes ( and gradients), but has higher processing time.
( Implemented in our OCR Project: http://sourceforge.net/projects/javaocr/ , and you can see it in action
in this application: https://market.android.com/details?id=de.pribluda.android.ocrcall&feature=search_result )

Related

create a mask from bitmap

I have an image as bitmap e.g
I want to create mask programmatically from that bitmap like this
I searched online but did not find any solution.
2003 Java Q and A about Masking Images
The question posed on this website seems similar to yours and the answers should help you out. Their code was written in Java back in 2003, but I believe you are asking about something you plan to program in Android Studio from your tags in I am guessing Java. Your question is kind of vague, but maybe this website will be a good starting point. There are longer solutions, with complete code written out, but I'll post one of the solutions listed.
One of the Solutions posted on that forum is this:
//get the image pixel
int imgPixel = image.getRGB(x,y);
//get the mask pixel
int maskPixel = mask.getRGB(x,y);
//now, get rid of everything but the blue channel
//and shift the blue channel into the alpha channels sample space.
maskPixel = (maskPixel &0xFF)<<24
//now, merge img and mask pixels and copy them back to the image
image.setRGB(x,y,imgPixel|maskPixel);
I found a solution to my problem i solved my problem by tinting my bitmap using PorterDuffColorFilter in a following way.
public Bitmap tintBitmap(Bitmap bitmap, int color) {
Paint paint = new Paint();
paint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
Bitmap bitmapResult = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmapResult);
canvas.drawBitmap(bitmap, 0, 0, paint);
return bitmapResult;
}

Blurring a Rect within a screenshot

I'm developing an Android app which uses a background Service to programmatically capture a screenshot of whatever is on the screen currently. I obtain the screenshot as a Bitmap.
Next, I successfully imported OpenCV into my Android project.
What I need to do now is blur a subset of this image, i.e. not the entire image itself, but a [rectangular] area or sub-region within the image. I have an array of Rect objects representing the rectangular regions that I need to blur within the screenshot.
I've been looking around for a tutorial on doing this with OpenCV in Java, and I haven't found a clear answer. The Mat and Imgproc classes are obviously the ones of interest, and there's the Mat.submat() method, but I've been unable to find a clear, straightforward tutorial on getting this done.
I've googled a lot, and none of the examples I've found are complete. I need to do this in Java, within the Android runtime.
What I need is: Bitmap >>> Mat >>> Imgproc>>> Rect >>> Bitmap with ROI
blurred.
Any experienced OpenCV devs out here, can you point me in the right direction? This is the only thing I'm stuck at.
Related:
Gaussian blurring with OpenCV: only blurring a subregion of an image?.
How to blur a rectagle with OpenCv.
How to blur some portion of Image in Android?.
The C++ code to achieve this task is shared below with comments and sample images:
// load an input image
Mat img = imread("C:\\elon_tusk.png");
img:
// extract subimage
Rect roi(113, 87, 100, 50);
Mat subimg = img(roi);
subimg:
// blur the subimage
Mat blurred_subimage;
GaussianBlur(subimg, blurred_subimage, Size(0, 0), 5, 5);
blurred_subimage:
// copy the blurred subimage back to the original image
blurred_subimage.copyTo(img(roi));
img:
Android equivalent:
Mat img = Imgcodecs.imread("elon_tusk.png");
Rect roi = new Rect(113, 87, 100, 50);
Mat subimage = img.submat(roi).clone();
Imgproc.GaussianBlur(subimg, subimg, new Size(0,0), 5, 5);
subimg.copyTo(img.submat(roi));
You could just implement your own helper function, let's call it roi (region of interest).
Since images in opencv are numpy ndarrays, you can do something like this:
def roi(image: np.ndarray, region: QRect) -> np.ndarray:
a1 = region.upperLeft().x()
b1 = region.bottomRight().y()
a2 = region.upperLeft().x()
b2 = region.bottomRight().y()
return image[a1:a2, b1:b2]
And just use this helper function to extract the subregions of the image that you are interested, blur them and put the result back on the original picture.

Android Canvas matrix

For a school project I need to make a module to shrink a bitmap. So I made a matrix for this but when I draw directly the bitmap with the matrix like this :
canvas.drawBitmap(Bmp, ShrinkMatrice, p);
This work very fine, but I need to assign this matrix into the Bmp so I used a second canvas like this :
Canvas SuperCanvas = new Canvas(Bmp);
SuperCanvas.drawBitmap(Bmp, ShrinkMatrice, p);
but when I look the result with this :
canvas.drawBitmap(Bmp, 0,0, p);
the result look like this ( see the picture on the link ), the rest of the page is not draw correctly ...
if someone can explain me this problem :/...
Thank you in advance...
(Sorry if I made some error it's my first time on stackoverflow )

How to create canvas with large Bitmap, draw on it, and then scale to screen size to conserve memory?

Simply put, I have a Bitmap resource that is 1800 x 1800 pix due to the detail I need. I create a canvas from the Bitmap and then draw on it. After drawing is complete, It's attached to an ImageView. It works fine on devices with large Heaps but on small devices, it crashes. The Bitmap needs to be the same size for all devices when added to the canvas because the coordinates that I draw to are precise locations on the Bitmap.
Here is my code
initialBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.VeryLargeBitmap);
mutableBitmap = initialBitmap.copy(Bitmap.Config.RGB_565, true);
canvas = new Canvas(mutableBitmap);
....draw stuff here
canvas.drawLine(x, y, x2, y2, paint);
ImageView.setImageBitmap(mutableBitmap);
ImageView..setAdjustViewBounds(true);
I'm sure there is a better way. I have looked into OpenGL but have not tried it yet. It looks to complex for what I'm trying to accomplish.
BitmapFactory.Options o = new BitmapFactory.Options();
o.inMutable = true;
initialBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.VeryLargeBitmap, o);
Doing this should remove the need to copy the bitmap to an immutable one. When you're done with it (saved to file or ready for a new one) do this:
initialBitmap.recycle();
initialBitmap = null;
To remove any reference to it (NOTE: recycle may not be necessary but I like it "to make sure").
EDIT:
Special note is that creating a Bitmap is CPU intensive so it'd be best to decode it in a thread and start drawing when it's ready. You should never create a Bitmap in an onDraw or draw method.

Drawing bitmaps with alpha channel: please advise... (some solutions and speed issues)

I have a rather big number of small bitmaps (100+, size about 40x40) each one have some opaque and some transparent parts and i need to paint them respecting these areas.
Bitmaps are in ARGB format, 888(rgb) plus a 256bit alpha channel, standard like in PNG format.
The only (working) way i found to draw them is the following approach:
create a bitmap (ARGB_8888)
fill the bitmap with the raw data
extract the alpha layer from the bitmap
create a BitmapShader (RGB_565) based on the original bitmap
Create a paint for the bitmap which uses the created shader
Then paint the alpha mask using the paint with the special BitmapShader.
The initialization code is run only once, of course:
void initializeTile( int t ){
// Allocate the bitmap:
Bitmap original_data = Bitmap.createBitmap( tile_w, tile_h, Bitmap.Config.ARGB_8888);
// Fill with raw data (this is actually native C++ code):
populateBitmap( original_data );
// Get the alpha mask:
tile_mask[ t ] = original_data.extractAlpha();
// Create the bitmap shader:
tile_data = original_data.copy( Bitmap.Config.RGB_565, false);
// Create the shader:
BitmapShader shader = new BitmapShader(tile_data, CLAMP, CLAMP);
// Create the paint:
tile_paint[ t ] = new Paint();
tile_paint[ t ].setDither(true);
tile_paint[ t ].setAntiAlias(true);
tile_paint[ t ].setFilterBitmap(true);
tile_paint[ t ].setShader( shader );
}
And the paint code is the most simple possible, and it's in the main draw loop:
void paintTile(t){
canvas.drawBitmap( tile_mask[ t ], tile_x[ t], tile_y[ t], tile_paint[ t] );
}
Now, on phones like the Ideos (Android 2.2) it run smooth and fine, but on other phones like the top-end Samsung Galaxy SII (Android 2.3) it's crappy and slow. This does not make much sense to me...
So, what do you think of this approach? Are there better, faster, ways to achieve the same result?
And, why do you think it's so slow on modern, fast hardware? Is there any ways to improve it?
Ok, after some work i found out a better solution. I cannot answer my own questions, so please do if you know more than me.
But, in case more people needs this, i am posting my new solution, which is much faster albeit a bit more complicated. The key idea is to use the shader approach ONLY during initialization and not for painting.
To do this, i create a new bitmap which will contain the "clipped" bitmap (with all the transparent areas cleared) using the shader approach, then paint that clipped bitmap without any shader in the draw code.
void initializeTile( int t ){
// Allocate the bitmap:
Bitmap original_data = Bitmap.createBitmap( tile_w, tile_h, Bitmap.Config.ARGB_8888);
// Fill with raw data (this is actually native C++ code):
populateBitmap( original_data );
// Now make a new bitmap to be clipped:
Bitmap clipped_data = Bitmap.createBitmap( tile_w, tile_h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(clipped_data);
Paint clip_paint = new Paint();
clip_paint.setDither(true);
clip_paint.setAntiAlias(true);
clip_paint.setFilterBitmap(true);
clip_paint.setShader( new BitmapShader(original_data, CLAMP, CLAMP));
// Paint the clipped bitmap:
canvas.drawBitmap( tile_mask[ t ], 0, 0, clip_paint );
//Use the clipped bitmap as original bitmap:
tile_data[ t ] = clipped_data;
}
And also drawing code:
void paintTile(t){
canvas.drawBitmap( tile_data[ t ], tile_x[ t], tile_y[ t], null );
}
Overall, this is much faster.
Still it's unclear to me WHY Android would not paint my alpha-channelled bitmaps properly without all this mess!

Categories

Resources