简体   繁体   中英

How can I make transparent background of a Bitmap?

I am working on a module in which I have to make background of bitmap image transparent. Actually, I am making an app like "Stick it" through which we can make sticker out of any image. I don't know from where to begin. Can someone give me a link or a hint for it?

Original Image- 在此处输入图片说明

After making background transparent-

在此处输入图片说明

This is what I want.

I can only provide some hints on how to approach your problem. You need to do a Image Segmenation . This can be achived via the k-means algotithm or similar clustering algorithms. See this for algorithms on image segmantation via clustering and this for a Java Code example. The computation of the clustering can be very time consumeing on a mobile device. Once you have the clustering you can use this approach to distinguish between the background and the foreground. In general all you picture should have a bachground color which differs strongly from the foreground otherwise it is not possible for the clustering to distunguish between them. It can also happen that a pixel inside of you foreground is assigned to the cluster of the background beacuase it has a similar color like your background. To prevent this from happening you could use this approach or a region grwoth algorithm . Afterward you can let you user select the clusters via touch and remove them. I also had the same problems with my Android App. This will give you a good start and once you have implemented the custering you just need to tewak the k parameter of the clustering to get good results.

Seems like a daunting task. If you are talking about image processing if I may understand then you can try https://developers.google.com/appengine/docs/java/images/ Also if you want to mask the entire background ( I have not tried Stick it) the application needs to understand the background image map. Please provide some examples so that I can come up with more definitive answers

if you are working in Android you might need a Buffer to get the pixels from the image - it's a intBuffer and it reduces the memory usage enormously... to get data from and stor data into the Buffer you have three methods (you can skip that part if you don't have 'large' images):

private IntBuffer buffer;
public void copyImageIntoBuffer(File imgSource) {
    final Bitmap temp = BitmapFactory.decodeFile(imgSource
            .getAbsolutePath());
    buffer.rewind();
    temp.copyPixelsToBuffer(buffer);
}

protected void copyBufferIntoImage(File tempFile) throws IOException {
    buffer.rewind();
    Bitmap temp = Bitmap.createBitmap(imgWidth, imgHeight,
            Config.ARGB_8888);
    temp.copyPixelsFromBuffer(buffer);

    FileOutputStream out = new FileOutputStream(tempFile);
    temp.compress(Bitmap.CompressFormat.JPEG, 90, out);
    out.flush();
    out.close();
}

public void mapBuffer(final File tempFile, long size) throws IOException {

    RandomAccessFile aFile = new RandomAccessFile(tempFile, "rw");
    aFile.setLength(4 * size); // 4 byte pro int
    FileChannel fc = aFile.getChannel();
    buffer = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size())
            .asIntBuffer();

}

now you can use the Buffer to get the pixels and modify them as desired... (i've copyied a code snipped that used a Progress bar on my UI and therefore needed a Handler/ProgressBar... when i did this i was working on bigger images and implemented a imageFilter (Gauss-Filter,Grey-Filter, etc.... just delete what is not needed)

public void run(final ProgressBar bar, IntBuffer buffer, Handler mHandler, int imgWidth, int imgHeight, int transparentColor ) {
     for (int dy = 0; dy < imgHeight; dy ++){

        final int progress = (dy*100)/imgHeight;

        for (int dx = 0; dx < imgWidth; dx ++ ){

            int px = buffer.get();
            //int a = (0xFF000000 & px);
            //int r = (0x00FF0000 & px) >> 16;
            //int g = (0x0000FF00 & px) >> 8;
            //int b = (0x000000FF & px);

            //this makes the color transparent
            if (px == transparentColor) {
                px = px | 0xFF000000;
            }


            //r = mid << 16;
            //g = mid << 8;
            //b = mid;
            //int col = a | r | g | b;

            int pos = buffer.position();
            buffer.put(pos-1, px);
        }

        // Update the progress bar
        mHandler.post(new Runnable() {                      
            public void run() {
                bar.setProgress(progress);                          
            }
        });

    }
}

if you really have small images, you can get the pixels directly during onCreate() or even better create a Buffer (maybe a HashMap or a List) before you start the Activity...

One possibility would be to utilize the floodfill operation in the openCV library. There are lots of examples and tutorials on how to do similar stuff to what you want and OpenCV has been ported to Android. The relevant terms to Google are of course "openCV" and "floodfill".

For this kind of task(and app) you'll have to use openGL. Usually when working on openGL you based your fragment shader on modules you build in Matlab. Once you have the fragment shader it's quite easy to apply it on image. check this guide how to do it.

Here's a link to remove background from image in MatLab

I'm not fully familiar with matlab and if it can generate GLSL code by itself(the fragment shader). But even if it doesn't - you might want to learn GLSL yourself because frankly - you are trying to build a graphics app and Android SDK is somehow short when using it for images manipulation, and most important is that without a strong hardware-acceleration engine behind it - I cannot see it works smooth enough.

Once you'll have the figure image - you can apply it on transparent background easily like this:

Canvas canvas = new Canvas(canvasBitmap);
canvas.drawColor(Color.TRANSPARENT);   
BitmapDrawable bd = (BitmapDrawable) getResources().getDrawable(R.drawable.loading);    
Bitmap yourBitmap = bd.getBitmap();    
Paint paint = new Paint();    
canvas.drawBitmap(yourBitmap, 0, 0, paint);
Bitmap newBitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(),image.getConfig());
Canvas canvas = new Canvas(newBitmap);
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(image, 0, 0, null);

OR See this

hope this wll helps you

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM