I am developing an Image manipulation software in android.i want to change the brightness of an particular image.how it can be done in code?
I'm using something like this at the moment:
if (brighter)
{
darknessPaint.setColorFilter(new PorterDuffColorFilter(Color.argb(level, 255, 255, 255), Mode.SRC_OVER));
}
else
{
darknessPaint.setColorFilter(new PorterDuffColorFilter(Color.argb(level, 0, 0, 0), Mode.SRC_ATOP));
}
darknessCanvas.setBitmap(dst);
darknessCanvas.drawBitmap(src, 0, 0, darknessPaint);
Indeed you could use LightningColorFilter too or ColorMatrixColorFilter. If anyone has a better (and by that I mean faster, besides using JNI which I haven't tried yet) method please let me know.
You probably want to look at LightingColorFilter and Drawable, or if you want to perform the manipulation manually, look at Bitmap - specifically getPixels and setPixels (or copyPixelsFromBuffer and copyPixelsToBuffer if you wish).
Related
I need to compare two images to find the equality . I have searched a lot about AR and openCV. Already gone through compare two images in android and Tried OpenCV samples too . With OPENCV only ORB is free to use and it will compare images in GrayScale and thats not what i need.
P.S:- The need is i have 4 images of a object in my app. SO if user scan a real object using camera then i need to figure out the object in this scanned image does match any of the object in those 4 images or not. I know it way off-topic and also too broad as per SO standard but I really need help on this.
EDIT:- After trying some algos from github i stumble upon on This project . And the results are quite satisfying . I already have tested it with several templates . I am stuck here with one problem . I need to show to user whether the object found or not(a boolean) . How can i determine this if object is detected correctly or not ?
Putting some final step code below.
Point point1=new Point(sceneCorners.get(0,0));
Point point2=new Point(sceneCorners.get(1,0));
Point point3=new Point(sceneCorners.get(2,0));
Point point4=new Point(sceneCorners.get(3,0));
Imgproc.line(rgb, point1, point2, new Scalar(0, 255, 0), 4);
Imgproc.line(rgb, point2, point3, new Scalar(0, 255, 0), 4);
Imgproc.line(rgb, point3, point4, new Scalar(0, 255, 0), 4);
Imgproc.line(rgb, point4,point1, new Scalar(0, 255, 0), 4);
the 2 points are found on each detection . How can i determine that it detected the object or not ? Some things i already tried :
1. Check for rectangle formed with those points:- This can fail .
What is the recommended approach for solving this problem. I have searched a lot most of every sample on github but not found a solution for this .
Please let me know which approach should i follow ?
I am attempting to draw a line (with line()) with square endings, but can not find any documentation telling me how to do it. So far all my lines end in little triangles.
Can this be done? Is its something to do with lineType?
EDIT: An example of my usage...
line(ptr_to_mat, Point(10,25), Point(30,25), Scalar(255,0,0,0),4, 8, 0);
EDIT: I should have mentioned, this is running on an Android device.
According to OpenCV docs, function line() will draw thick lines with rounding endings.
That said, you cannot directly get over this. But, you can draw it several times with thickness=1 or draw a filled rectangle instead to achieve your goal (both ugly though :():
line(ptr_to_mat, Point(10,23), Point(30,23), CV_RGB(255,0,0), 1, 8, 0);
line(ptr_to_mat, Point(10,24), Point(30,24), CV_RGB(255,0,0), 1, 8, 0);
line(ptr_to_mat, Point(10,25), Point(30,25), CV_RGB(255,0,0), 1, 8, 0);
line(ptr_to_mat, Point(10,26), Point(30,26), CV_RGB(255,0,0), 1, 8, 0);
You will get:
Also from the Docs - "The line is clipped by the image boundaries." - maybe you can clip the round edges out of the line by drawing the line inside of a Mat's Region Of Interest (ROI, a.k.a. submat). Basically you have to set the dimensions of the ROI with the size of the line minus the round tips. If this sound too complex, it is simpler than that.
It is not very elegant but considering that the clipping is done for free within the line drawing algorithm this probably more efficient than drawing several lines / rectangles.
Another thing, try to change the lineType parameter, it might change the tip rendering.
lineType:
8 (or omitted) - 8-connected line.
4 - 4-connected line.
CV_AA - antialiased line.
Or you can always implement your own line renderer?
I never said it would be pretty :D
the topic is a bit old but I faced this problem recently and I found a solution by using the library wxpython. Maybe it could help, here is a code example:
import wx
app = wx.App()
frame = wx.Frame(None, title="Draw on Image")
imgBit = wx.Bitmap(width=512, height=512, depth=1)
dc = wx.MemoryDC(imgBit)
pen = wx.Pen(wx.RED, 3)
pen.SetCap(wx.CAP_BUTT)
dc.SetPen(pen)
dc.DrawLines(((32, 32), (64, 32)))
dc.SelectObject(wx.NullBitmap)
imgBit.SaveFile("bitmap.png", wx.BITMAP_TYPE_PNG)
Hope it will help someone in the future
Wanted to achieve something like this: http://www.leptonica.com/binarization.html
While searching for solutions, most of the answers were general instructions such as advise to look at adaptive filter, gaussian blur, dilation and erosion but none of them provide any sample code to start with (so can play around with the values)..
I know different image require different methods and values to achieve optimum clarity, but I just need some general filter so that the image at least slightly sharper and less noisy compare to the original, before doing any OCR on it.
this is what I've tried so far..
Mat imageMat = new Mat();
Utils.bitmapToMat(photo, imageMat);
Imgproc.cvtColor(imageMat, imageMat, Imgproc.COLOR_BGR2GRAY);
Imgproc.GaussianBlur(imageMat, imageMat, new Size(3, 3), 0);
Imgproc.adaptiveThreshold(imageMat, imageMat, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 5, 4);
but being an image processing newb, obviously I don't know what I'm doing XD
original image:
after applying the above:
How to do it correctly?
UPDATE: got it much closer thanks to metsburg, berak and Aurelius
Using the medianBlur method since cvSmooth with CV_MEDIAN is deprecated and replaced with medianBlur:
Imgproc.medianBlur(imageMat, imageMat, 3);
Imgproc.threshold(imageMat, imageMat, 0, 255, Imgproc.THRESH_OTSU);
Result:
Using back the GaussianBlur method, the result actually is slightly better:
Imgproc.GaussianBlur(imageMat, imageMat, new Size(3, 3), 0);
Imgproc.threshold(imageMat, imageMat, 0, 255, Imgproc.THRESH_OTSU);
Result:
For this image the difference is not noticable, so I tried another image which is a photo taken off the computer screen. Computer screen gives a lot of noises (wavy lines) so it is very hard to remove the noise.
Example original image:
Directly applying otsu:
using medianBlur before otsu:
using GaussianBlur before otsu:
Seems like gaussian blur is slightly better, however I'm still playing with the settings..
If anyone can advise on how to improve the computer screen photo further, please, let us know :)
One more thing.. using this method on the image inside the top link yields horrible results :( see it here: http://imgur.com/vOZAaE0
Well, you're almost there. Just try these modifications:
Instead of
Imgproc.GaussianBlur(imageMat, imageMat, new Size(3, 3), 0);
try:
cvSmooth(imageMat, imageMat, CV_MEDIAN, new Size(3, 3), 0);
check the syntax, may not exactly match
The link you posted uses thresholding of Otsu, so try this:
Imgproc.threshold(imageMat, imageMat, 0, 255, Imgproc.THRESH_OTSU);
for thresholding.
Try tweaking the parameters here and there, you should get something pretty close to your desired outcome.
Instead of using Imgproc.THRESH_BINARY_INV use Imgproc.THRESH_BINARY only as _INV is inverting your image after binarisations and resulted is the said output shown above in your example.
correct code:
Imgproc.adaptiveThreshold(imageMat, imageMat, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 5, 4);
I'm trying to create an Android app that adds a random quote to images.
The general process is this:
Start from a custom given image that shows when starting the app.
From this image all the user can do is tap on it and generate a new random "quote" that get overlaid on the image.
The user can save the newly created image with the quote he chose and set it as wallpaper.
I have got to the point where I can display the image in an ImageView.
My list of quotes is stored in my strings.xml file.
I do something like this in an app. Use Canvas.
I edited down a piece of my code, which actually adds a couple of other images on the background and stuff too.
Meat of code:
private static Bitmap getPoster(...) {
Bitmap background = BitmapFactory.decodeResource(res, background_id)
.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(background);
Typeface font = Typeface.createFromAsset(res.getAssets(), FONT_PATH);
font = Typeface.create(font, Typeface.BOLD);
Paint paint = new Paint();
paint.setTypeface(font);
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
paint.setStyle(Style.FILL);
paint.setShadowLayer(2.0f, 1.0f, 1.0f, Color.BLACK);
float fontSize = getFontSize(background.getWidth(), THE_QUOTE, paint); //You'll have to define a way to find a size that fits, or just use a constant size.
paint.setTextSize(fontSize);
canvas.drawText(THE_QUOTE, (background.getWidth() - paint.measureText(THE_QUOTE)) / 2,
background.getHeight() - FILLER_HEIGHT, paint); //You might want to do something different. In my case every image has a filler in the bottom which is 50px.
return background;
}
Put your own version of that in a class and feed it the image id and anything else. It returns a bitmap for you to do whatever you want with (display it in an imageview, let the user save it and set as wallpape).
I know i did this for the PC with imagemagick a few years ago(save image with text on)
Seems like imagemagick have been ported to android, so I would start digging into thier documentation.
https://github.com/lilac/Android-ImageMagick
Ok! Francesco my friend, I've an idea although not a working code ('cuz I'm not really good at it). So, here it is:
Implement an onClickListener() on your ImageView like below:
ImageView iv = (ImageView)findViewById(R.id.imageview1);
iv.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
/** When I say do your stuff here, I mean read the user input and set your wallpaper here. I'm sorry that I don't really know how to save/set the wallpaper */
}
});
When it comes to reading user input/generating random quotes, you can do this:
You said you already have the quotes saved in the strings.xml file. Using the ids of those strings, I think you can implement a switch case scenario where it uses java imports - java.util.Scanner and java.util.Random. Ultimately, using these in your ImageView onClickListener could/should result in the desired output.
I know my answer is too vague, but I've a faint hope that it has given you a minute lead as to what you can implement. I seriously hope there are better answers than this. If not, then I hope this helps you some, and I also hope that I'm not leading you in the wrong direction since this is just a mere speculation. Sorry, but this is all I've got.
I'm trying to port an emulator that i have written in java to android. Things have been going nicely, I was able to port most of my codes with minor changes however due to how emulation works, I need to render image at pixel level.
As for desktop java I use
int[] pixelsA = ((DataBufferInt) src.getRaster().getDataBuffer()).getData();
which allow me to get the reference to the pixel buffer and update it on the fly(minimize object creations)
Currently this is what my emulator for android does for every frame
#Override
public void onDraw(Canvas canvas)
{
buffer = Bitmap.createBitmap(pixelsA, 256, 192, Bitmap.Config.RGB_565);
canvas.drawBitmap(buffer, 0, 0, null);
}
pixelsA is an array int[], pixelsA contains all the colour informations, so every frame it will have to create a bitmap object by doing
buffer = Bitmap.createBitmap(pixelsA, 256, 192, Bitmap.Config.RGB_565);
which I believe is quite expensive and slow.
Is there any way to draw pixels efficiently with canvas?
One quite low-level method, but working fine for me (with native code):
Create Bitmap object, as big as your visible screen.
Also create a View object and implement onDraw method.
Then in native code you'd load libjnigraphics.so native library, lookup functions AndroidBitmap_lockPixels and AndroidBitmap_unlockPixels.
These functions are defined in Android source in bitmap.h.
Then you'd call lock/unlock on a bitmap, receiving address to raw pixels. You must interpret RGB format of pixels accordingly to what it really is (16-bit 565 or 32-bit 8888).
After changing content of the bitmap, you want to present this on screen.
Call View.invalidate() on your View. In its onDraw, blit your bitmap into given Canvas.
This method is very low level and dependent on actual implementation of Android, however it's very fast, you may get 60fps no problem.
bitmap.h is part of Android NDK since platform version 8, so this IS official way to do this from Android 2.2.
You can use the drawBitmap method that avoids creating a Bitmap each time, or even as a last resort, draw the pixels one by one with drawPoint.
Don't recreate the bitmap every single time. Try something like this:
Bitmap buffer = null;
#Override
public void onDraw(Canvas canvas)
{
if(buffer == null) buffer = Bitmap.createBitmap(256, 192, Bitmap.Config.RGB_565);
buffer.copyPixelsFromBuffer(pixelsA);
canvas.drawBitmap(buffer, 0, 0, null);
}
EDIT: as pointed out, you need to update the pixel buffer. And the bitmap must be mutable for that to happen.
if pixelsA is already an array of pixels (which is what I would infer from your statement about containing colors) then you can just render them directly without converting with:
canvas.drawBitmap(pixelsA, 0, 256, 0, 0, 256, 192, false, null);