am using camera2 api to capture multiple images as one and after that i save the image and creating a panorama images
private Bitmap combineImageIntoOne(ArrayList<Bitmap> bitmap) {
int w = 0, h = 0;
for (int i = 0; i < bitmap.size(); i++) {
if(i < bitmap.size() - 1){
h = bitmap.get(i).getHeight() > bitmap.get(i + 1).getHeight() ? bitmap.get(i).getHeight() : bitmap.get(i + 1).getHeight();
}
w += bitmap.get(i).getWidth();
}
Bitmap temp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(temp);
float aspectRatio = 0;
int side = 0;
int width = 0;
for (int i = 0; i < bitmap.size(); i++) {
Log.d("HTML", "Combine: "+i+"/"+bitmap.size()+1);
side = (i == 0 ? 0 : side+bitmap.get(i).getWidth());
canvas.drawBitmap(bitmap.get(i), 0f, side, null);
}
return temp;
}
scaling it down become more difficult does any one have an idea how I can dealt with horizontal image merge with 20 items?What code did you use to resolve this problem?
private Bitmap mergeMultiple(ArrayList<Bitmap> parts) {
int w = 0, h = 0;
for (int i = 0; i < parts.size(); i++) {
if (i < parts.size() - 1) {
w = parts.get(i).getWidth() > parts.get(i + 1).getWidth() ? parts.get(i).getWidth() : parts.get(i + 1).getWidth();
}
h += parts.get(i).getHeight();
}
Bitmap temp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(temp);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
int top = 0;
for (int i = 0; i < parts.size(); i++) {
top = (i == 0 ? 0 : top + parts.get(i).getHeight() + 100);
canvas.drawBitmap(parts.get(i), 0f, top,paint );
}
return temp;
}
Related
Save segmentation result of Selfie segmentation with ML Kit on Android as A Bitmap with transparent background
I am following this tutorial and code for Selfie segmentation
Here
I have referred this code from the tutorial
ByteBuffer mask = segmentationMask.getBuffer();
int maskWidth = segmentationMask.getWidth();
int maskHeight = segmentationMask.getHeight();
for (int y = 0; y < maskHeight; y++) {
for (int x = 0; x < maskWidth; x++) {
// Gets the confidence of the (x,y) pixel in the mask being in the foreground.
float foregroundConfidence = mask.getFloat();
}
}
Which generates a Mask
Then I have Referred the Sample app Which generates a purple background Mask
Here
using this code
#ColorInt
private int[] maskColorsFromByteBuffer(ByteBuffer byteBuffer) {
#ColorInt int[] colors = new int[maskWidth * maskHeight];
for (int i = 0; i < maskWidth * maskHeight; i++) {
float backgroundLikelihood = 1 - byteBuffer.getFloat();
if (backgroundLikelihood > 0.9) {
colors[i] = Color.argb(128, 255, 0, 255);
} else if (backgroundLikelihood > 0.2) {
// Linear interpolation to make sure when backgroundLikelihood is 0.2, the alpha is 0 and
// when backgroundLikelihood is 0.9, the alpha is 128.
// +0.5 to round the float value to the nearest int.
int alpha = (int) (182.9 * backgroundLikelihood - 36.6 + 0.5);
colors[i] = Color.argb(alpha, 255, 0, 255);
}
}
return colors;
}
Now I want to generate an Image with the original images detected mask and Overlay it on a Transparent Image and save that bitmap for this I am using this code
public Bitmap generateMaskBgImage(Bitmap image, Bitmap bg) {
//Bg is Transparent Png Image.
Bitmap bgBitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), image.getConfig());
for (int y = 0; y < maskHeight; y++) {
for (int x = 0; x < maskWidth; x++) {
int bgConfidence = (int) ((1.0 - maskBuffer.getFloat()) * 255);
int bgPixel = bg.getPixel(x, y);
bgPixel = ColorUtils.setAlphaComponent(bgPixel, bgConfidence);
bgBitmap.setPixel(x, y, bgPixel);
}
}
maskBuffer.rewind();
return bitmapUtils.mergeBitmaps(image, bgBitmap);
}
However it generates an Image with the desired mask but with a Black back ground, How can we save that image with Transparent background.
You can try this (color1 is the color you set in the mask):
private Bitmap performBW(Bitmap originBitmap,Bitmap maskBitmap) {
Bitmap bmOut = Bitmap.createBitmap(originBitmap.getWidth(), originBitmap.getHeight(),
originBitmap.getConfig());
int w = originBitmap.getWidth();
int h = originBitmap.getHeight();
int[] colors = new int[w * h];
int[] colorsMask=new int[maskBitmap.getWidth() * maskBitmap.getHeight()];
originBitmap.getPixels(colors, 0, w, 0, 0, w, h);
maskBitmap.getPixels(colorsMask, 0, w, 0, 0, w, h);
int pos;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
pos = i * w + j;
if (colorsMask[pos] == color1) colors[pos]=Color.TRANSPARENT;
}
}
bmOut.setPixels(colors, 0, w, 0, 0, w, h);
return bmOut;
}
I tried to make my own implementation of Otsu. I already read some source code from java and some sites that explains the formula and tried to implement it. I want to share this to ask if anyone can help me or at least tell about what can I do or improve.
I already coded get width, height and the background and foreground weight, mean, variance, and within class variance.
Note that I have not implemented how to set or find the exact threshold or even change the picture to black-white(binarize) using within class variance. If you can help me, feel welcome to. I also see some java codes that has treshhold = i or treshhold = t but I can't see how they made the image to black-white.
Here is my code:
Otsu.java
Bitmap tempImg = (Bitmap) original;
Bitmap OImg = Bitmap.createBitmap(tempImg.getWidth(), tempImg.getHeight(), tempImg.getConfig());
int width = tempImg.getWidth();
int height = tempImg.getHeight();
int A, R, G, B,colorPixel;
for (int x = 0; x < width; x++) { //original image to grayscale
for (int y = 0; y < height; y++) {
colorPixel = tempImg.getPixel(x, y);
A = Color.alpha(colorPixel);
R = Color.red(colorPixel);
G = Color.green(colorPixel);
B = Color.blue(colorPixel);
R = (R + G + B) / 3;
G = R;
B = R;
OImg.setPixel(x, y, Color.argb(A, R, G,B ));
}
}
return OImg;
}
public static Bitmap Botsu(Bitmap gImg){
Bitmap tempImg = (Bitmap) gImg;
Bitmap BWimg = Bitmap.createBitmap(tempImg.getWidth(), tempImg.getHeight(), tempImg.getConfig());
int width = tempImg.getWidth();
int height = tempImg.getHeight();
int A, R, G, B, colorPixel;
// histo-thresh
double Wcv = 0;
int[] Bx = new int[256];
int[] By = new int[256];
int[] Fx = new int[256];
int[] Fy = new int[256];
double Bw =0, Bm =0, Bv =0, Bp = 0;
double Fw =0, Fm =0, Fv =0, Fp = 0;
int c = 0, ImgPix = 0, ImgPixB = 0, ImgPixF = 0, newPixel = 0;
// pixel check for histogram
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
colorPixel = tempImg.getPixel(x, y);
A = Color.alpha(colorPixel);
R = Color.red(colorPixel);
G = Color.green(colorPixel);
B = Color.blue(colorPixel);
int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B);
if (gray > 128) { // white - foreground
for (int z=0; z<Fx.length; z++){
if (Fx[z] == gray){
c++;
}
}
if (c==1){
Fy[gray] = Fy[gray]+1; //y axis - counter for pixels for each x
}
else{
Fx[x] = gray; //x axis - 0-255
Fy[gray] = Fy[gray]+1;
}
}//By[Bx[x]]
else{ // black - background
for (int z=0; z<Bx.length; z++){
if (Bx[z] == gray){
c++;
}
}
if (c==1){
By[gray] = By[gray]+1; //y axis - counter for pixels for each x
}
else{
Bx[x] = gray; //x axis - 0-255
By[gray] = By[gray]+1;
}
}
}
}
for (int b=0; b<By.length; b++){
ImgPixB = ImgPixB + By[b];
}
for (int f=0; f<Fy.length; f++){
ImgPixF = ImgPixF + Fy[f];
}
ImgPix = ImgPixB + ImgPixF;
//bg part hist
for (int i=0; i<By.length; i++){ //weight
Bw = Bw + By[i];
}
Bw = Bw/ImgPix;
for (int i=0; i<By.length; i++){ //pixel sum
Bp = Bp + By[i];
}
for (int i = 0; i<Bx.length; i++){ //mean
Bm = Bm + (Bx[i]*By[Bx[i]]);
}
Bm = Bm/Bp;
for (int i=0; i<Bx.length; i++){ //variance
Bv = Bv + (Math.pow((Bx[i]-Bm),2)*By[Bx[i]]); // (Bx[i]-Bm) * (Bx[i]-Bm)
}
Bv = Bv/Bp;
//fg part hist
for (int i=0; i<Fy.length; i++){ //weight
Fw = Fw + Fy[i];
}
Fw = Fw/ImgPix;
for (int i=0; i<Fy.length; i++){ //pixel sum
Fp = Fp + Fy[i];
}
for (int i = 0; i<Fx.length; i++){ //mean
Fm = Fm + (Fx[i]*Fy[Fx[i]]);
}
Fm = Fm/Fp;
for (int i=0; i<Fx.length; i++){ //variance
Fv = Fv + (Math.pow((Fx[i]-Fm),2)*Fy[Fx[i]]); // (Bx[i]-Bm) * (Bx[i]-Bm)
}
Fv = Fv/Fp;
// within class variance
Wcv = (Bw * Bv) + (Fw * Fv);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
colorPixel = tempImg.getPixel(x, y);
A = Color.alpha(colorPixel);
R = Color.red(colorPixel);
G = Color.green(colorPixel);
B = Color.blue(colorPixel);
//int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B);
int gray2 = (int) (Wcv * R + Wcv * G + Wcv * B);
if (gray2 > 128) {
gray2 = 255;
}
else if (gray2 <129){
gray2 = 0;
}
BWimg.setPixel(x, y, Color.argb(A, gray2, gray2, gray2));
}
}
return BWimg;
x[z] is for x-axis andy[gray] is for y-axis. I based this on the graph on Lab Book
x = 0-255
y = how many pixels is on a certain color shade
feel free to send more samples that can help me.
OUTPUT: (I added 2 function with 3 output that has an output. Other value will only return few black dots or just white image.)
if (gray2 > 128) {
gray2 = 255;
}
else if (gray2 < 129){
gray2 = 0;
}
if (gray2 > 64 && gray2 < 129) {
gray2 = 255;
}
else if (gray2 < 65){
gray2 = 0;
}
In my application a user can upload some pictures and for database size limits I would like to merge these images to create only one image, I do that with:
private Bitmap combineImageIntoOne(ArrayList<Bitmap> bitmap) {
int w = 0, h = 0;
for (int i = 0; i < bitmap.size(); i++) {
if (i < bitmap.size() - 1) {
w = bitmap.get(i).getWidth() > bitmap.get(i + 1).getWidth() ? bitmap.get(i).getWidth() : bitmap.get(i + 1).getWidth();
}
h += bitmap.get(i).getHeight();
}
Bitmap temp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(temp);
int top = 0;
for (int i = 0; i < bitmap.size(); i++) {
Log.d("HTML", "Combine: "+i+"/"+bitmap.size()+1);
top = (i == 0 ? 0 : top+bitmap.get(i).getHeight());
canvas.drawBitmap(bitmap.get(i), 0f, top, null);
}
return temp;
}
Bitmap.compress is the method you are looking for - it allows you to save Bitmap to any OutputStream you want.
bitmap.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(someFile));
I am currently working on zip animation to unlock android mobile screen. Changing background images is a expensive task and have not a smooth effect. I want a smooth effect in it. Any help please? Thanks
Try this:
The smooth effect makes use of Convolution Matrix:
Some image effects are better to implement using Convolution Matrix
method like: Gaussian Blur, Sharpening, Embossing, Smooth…
Check That Link to know more about Convolution Matrix or Another one
To do Convolution Matrix
import android.graphics.Bitmap;
import android.graphics.Color;
public class ConvolutionMatrix
{
public static final int SIZE = 3;
public double[][] Matrix;
public double Factor = 1;
public double Offset = 1;
public ConvolutionMatrix(int size) {
Matrix = new double[size][size];
}
public void setAll(double value) {
for (int x = 0; x < SIZE; ++x) {
for (int y = 0; y < SIZE; ++y) {
Matrix[x][y] = value;
}
}
}
public void applyConfig(double[][] config) {
for(int x = 0; x < SIZE; ++x) {
for(int y = 0; y < SIZE; ++y) {
Matrix[x][y] = config[x][y];
}
}
}
public static Bitmap computeConvolution3x3(Bitmap src, ConvolutionMatrix matrix) {
int width = src.getWidth();
int height = src.getHeight();
Bitmap result = Bitmap.createBitmap(width, height, src.getConfig());
int A, R, G, B;
int sumR, sumG, sumB;
int[][] pixels = new int[SIZE][SIZE];
for(int y = 0; y < height - 2; ++y) {
for(int x = 0; x < width - 2; ++x) {
// get pixel matrix
for(int i = 0; i < SIZE; ++i) {
for(int j = 0; j < SIZE; ++j) {
pixels[i][j] = src.getPixel(x + i, y + j);
}
}
// get alpha of center pixel
A = Color.alpha(pixels[1][1]);
// init color sum
sumR = sumG = sumB = 0;
// get sum of RGB on matrix
for(int i = 0; i < SIZE; ++i) {
for(int j = 0; j < SIZE; ++j) {
sumR += (Color.red(pixels[i][j]) * matrix.Matrix[i][j]);
sumG += (Color.green(pixels[i][j]) * matrix.Matrix[i][j]);
sumB += (Color.blue(pixels[i][j]) * matrix.Matrix[i][j]);
}
}
// get final Red
R = (int)(sumR / matrix.Factor + matrix.Offset);
if(R < 0) { R = 0; }
else if(R > 255) { R = 255; }
// get final Green
G = (int)(sumG / matrix.Factor + matrix.Offset);
if(G < 0) { G = 0; }
else if(G > 255) { G = 255; }
// get final Blue
B = (int)(sumB / matrix.Factor + matrix.Offset);
if(B < 0) { B = 0; }
else if(B > 255) { B = 255; }
// apply new pixel
result.setPixel(x + 1, y + 1, Color.argb(A, R, G, B));
}
}
// final image
return result;
}
}
Then to do Smooth effect
public static Bitmap smooth(Bitmap src, double value) {
ConvolutionMatrix convMatrix = new ConvolutionMatrix(3);
convMatrix.setAll(1);
convMatrix.Matrix[1][1] = value;
convMatrix.Factor = value + 8;
convMatrix.Offset = 1;
return ConvolutionMatrix.computeConvolution3x3(src, convMatrix);
}
You can change values and get the smooth effect as you want.
That tutorial it's found HERE
I've got a question regarding Bitmaps in Android: I 've got a Bitmap with white margins [size unknown] around. Is it possible to create a new Bitmap with all the white margins removed (rectangular shape)?
Bitmap bmp = Bitmap.createBitmap(width, bmpheigth, Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
canvas.setBitmap(bmp);
canvas.drawColor(Color.WHITE);
// draw here things!
It is asumed to be unknown where are things painted.
What is a good way to do that?
thanks!
Thanks #Maxim Efimov & #StackOverflowException
Just in Case Someone will need a snippet for this kind of problems:
this method returns a cut out smaller Bitmap with Margins removed. passing the pixels to a int-array first and then working with the array is a bit faster than the Bitmap.getPixel method
just call the method indicating Source Bitmap and Background color.
Bitmap bmp2 = removeMargins(bmp, Color.WHITE);
private static Bitmap removeMargins2(Bitmap bmp, int color) {
// TODO Auto-generated method stub
long dtMili = System.currentTimeMillis();
int MTop = 0, MBot = 0, MLeft = 0, MRight = 0;
boolean found1 = false, found2 = false;
int[] bmpIn = new int[bmp.getWidth() * bmp.getHeight()];
int[][] bmpInt = new int[bmp.getWidth()][bmp.getHeight()];
bmp.getPixels(bmpIn, 0, bmp.getWidth(), 0, 0, bmp.getWidth(),
bmp.getHeight());
for (int ii = 0, contX = 0, contY = 0; ii < bmpIn.length; ii++) {
bmpInt[contX][contY] = bmpIn[ii];
contX++;
if (contX >= bmp.getWidth()) {
contX = 0;
contY++;
if (contY >= bmp.getHeight()) {
break;
}
}
}
for (int hP = 0; hP < bmpInt[0].length && !found2; hP++) {
// looking for MTop
for (int wP = 0; wP < bmpInt.length && !found2; wP++) {
if (bmpInt[wP][hP] != color) {
Log.e("MTop 2", "Pixel found #" + hP);
MTop = hP;
found2 = true;
break;
}
}
}
found2 = false;
for (int hP = bmpInt[0].length - 1; hP >= 0 && !found2; hP--) {
// looking for MBot
for (int wP = 0; wP < bmpInt.length && !found2; wP++) {
if (bmpInt[wP][hP] != color) {
Log.e("MBot 2", "Pixel found #" + hP);
MBot = bmp.getHeight() - hP;
found2 = true;
break;
}
}
}
found2 = false;
for (int wP = 0; wP < bmpInt.length && !found2; wP++) {
// looking for MLeft
for (int hP = 0; hP < bmpInt[0].length && !found2; hP++) {
if (bmpInt[wP][hP] != color) {
Log.e("MLeft 2", "Pixel found #" + wP);
MLeft = wP;
found2 = true;
break;
}
}
}
found2 = false;
for (int wP = bmpInt.length - 1; wP >= 0 && !found2; wP--) {
// looking for MRight
for (int hP = 0; hP < bmpInt[0].length && !found2; hP++) {
if (bmpInt[wP][hP] != color) {
Log.e("MRight 2", "Pixel found #" + wP);
MRight = bmp.getWidth() - wP;
found2 = true;
break;
}
}
}
found2 = false;
int sizeY = bmp.getHeight() - MBot - MTop, sizeX = bmp.getWidth()
- MRight - MLeft;
Bitmap bmp2 = Bitmap.createBitmap(bmp, MLeft, MTop, sizeX, sizeY);
dtMili = (System.currentTimeMillis() - dtMili);
Log.e("Margin 2",
"Time needed " + dtMili + "mSec\nh:" + bmp.getWidth() + "w:"
+ bmp.getHeight() + "\narray x:" + bmpInt.length + "y:"
+ bmpInt[0].length);
return bmp2;
}
Use Bitmap.createBitmap(source, x, y, width, height) so knowing the white margin size you can do what you want.
My solution:
private Bitmap trim(Bitmap bitmap, int trimColor){
int minX = Integer.MAX_VALUE;
int maxX = 0;
int minY = Integer.MAX_VALUE;
int maxY = 0;
for(int x = 0; x < bitmap.getWidth(); x++){
for(int y = 0; y < bitmap.getHeight(); y++){
if(bitmap.getPixel(x, y) != trimColor){
if(x < minX){
minX = x;
}
if(x > maxX){
maxX = x;
}
if(y < minY){
minY = y;
}
if(y > maxY){
maxY = y;
}
}
}
}
return Bitmap.createBitmap(bitmap, minX, minY, maxX - minX + 1, maxY - minY + 1);
}
It isn't very fast, for 1280 x 576 px bitmap execution took 2965ms on Xiaomi Redmi 3S.
If it possible scale down image before triming:
private Bitmap scaleDown(Bitmap bitmap, float maxImageSize, boolean filter) {
float ratio = Math.min(maxImageSize / bitmap.getWidth(), maxImageSize / bitmap.getHeight());
int width = Math.round(ratio * bitmap.getWidth());
int height = Math.round(ratio * bitmap.getHeight());
return Bitmap.createScaledBitmap(bitmap, width, height, filter);
}
Late to the party, but this variation is a bit faster and perhaps easier to read:
public static Bitmap imageWithMargin(Bitmap bitmap, int color, int maxMargin) {
int maxTop = 0, maxBottom = 0, maxLeft = 0, maxRight = 0;
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int[] bitmapArray = new int[width * height];
bitmap.getPixels(bitmapArray, 0, width, 0, 0, width, height);
// Find first non-color pixel from top of bitmap
searchTopMargin:
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (bitmapArray[width * y + x] != color) {
maxTop = y > maxMargin ? y - maxMargin : 0;
break searchTopMargin;
}
}
}
// Find first non-color pixel from bottom of bitmap
searchBottomMargin:
for (int y = height - 1; y >= 0; y--) {
for (int x = width - 1; x >= 0; x--) {
if (bitmapArray[width * y + x] != color) {
maxBottom = y < height - maxMargin ? y + maxMargin : height;
break searchBottomMargin;
}
}
}
// Find first non-color pixel from left of bitmap
searchLeftMargin:
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
if (bitmapArray[width * y + x] != color) {
maxLeft = x > maxMargin ? x - maxMargin : 0;
break searchLeftMargin;
}
}
}
// Find first non-color pixel from right of bitmap
searchRightMargin:
for (int x = width - 1; x >= 0; x--) {
for (int y = height - 1; y >= 0; y--) {
if (bitmapArray[width * y + x] != color) {
maxRight = x < width - maxMargin ? x + maxMargin : width;
break searchRightMargin;
}
}
}
return Bitmap.createBitmap(bitmap, maxLeft, maxTop, maxRight - maxLeft, maxBottom - maxTop);
}