[英]How can I make transparent background of a Bitmap?
我正在开发一个模块,其中必须使位图图像的背景透明。 实际上,我正在制作一个像“ Stick it”这样的应用程序,通过它我们可以在任何图像上制作贴纸。 我不知道从哪里开始。 有人可以给我链接或提示吗?
原始图片-
使背景透明后
这就是我要的。
我只能提供一些有关如何解决您的问题的提示。 您需要执行图像分割 。 这可以通过k均值算法或类似的聚类算法来实现。 见这 对通过聚类图像segmantation和算法 这对于一个Java代码示例。 聚类的计算在移动设备上可能非常耗时。 一旦有了群集,就可以使用这种方法来区分背景和前景。 通常,所有图片应具有与前景强烈不同的背景色,否则,群集之间就不会混淆。 也有可能发生,因为您的前景内部的像素与背景具有相似的颜色,因此将其分配给背景的群集。 为了防止这种情况的发生,您可以使用这种方法或区域增长算法 。 之后,您可以让用户通过触摸选择集群并将其删除。 我的Android应用程序也有同样的问题。 这将为您提供一个良好的开始,并且一旦实施了诱捕程序,您只需要调整聚类的k参数即可获得良好的结果。
似乎是一项艰巨的任务。 如果您说的是我可能理解的图像处理,那么可以尝试https://developers.google.com/appengine/docs/java/images/另外,如果您想遮盖整个背景(我还没有尝试过粘贴)应用程序需要了解背景图像图。 请提供一些示例,以便我得出更明确的答案
如果您在Android上工作,则可能需要一个Buffer来从图像中获取像素-这是一个intBuffer,它极大地减少了内存使用...要从Buffer中获取数据或将数据存储到Buffer中,您可以使用以下三种方法(您可以跳过如果您没有“大”图像,则该部分):
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();
}
现在您可以使用Buffer来获取像素并根据需要对其进行修改...(我已经复制了一段代码,该代码使用了UI上的进度条,因此需要Handler / ProgressBar ...当我这样做时,处理更大的图像并实现了imageFilter(高斯滤镜,灰色滤镜等...只需删除不需要的内容)
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);
}
});
}
}
如果您确实有小图像,则可以在onCreate()期间直接获取像素,甚至更好地在开始Activity之前创建一个Buffer(可能是HashMap或List)。
一种可能性是利用openCV库中的Floodfill操作。 关于如何做与您想要的东西类似的事情,有很多示例和教程,并且OpenCV已移植到Android。 Google的相关术语当然是“ openCV”和“ floodfill”。
对于此类任务(和应用程序),您必须使用openGL。 通常,在使用openGL时,您的片段着色器基于在Matlab中构建的模块。 一旦有了片段着色器,就可以很容易地将其应用于图像。 检查本指南的操作方法。
我对matlab以及它是否可以自己生成GLSL代码(片段着色器)并不完全熟悉。 但是,即使不是这样-坦率地说,您可能想自己学习GLSL-您正在尝试构建图形应用,而使用Android SDK进行图像处理时,它在某种程度上还是很短的,最重要的是,没有强大的硬件加速它背后的引擎-我看不到它工作得足够流畅。
获得图形图像后,您可以轻松地将其应用于透明背景,如下所示:
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);
或看到这个
希望这会帮助你
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.