我正在研究一个模块,我必须使位图图像的背景透明。实际上,我正在创建一个像#34;坚持它的应用程序#34;通过它我们可以从任何图像中制作贴纸。我不知道从哪里开始。 有人可以给我一个链接或提示吗?
原始图片 -
使背景透明 -
这就是我想要的。
答案 0 :(得分:1)
我只能提供一些有关如何解决问题的提示。您需要执行图像分段。这可以通过k-means algotithm或类似的聚类算法来实现。有关算法的图像分割算法,请参阅this 和this以获取Java代码示例。聚类的计算可以在移动设备上非常耗费时间。完成群集后,您可以使用this approach来区分背景和前景。一般来说,你所有的图片应该有一个与前景强烈不同的bachground颜色,否则聚类不可能在它们之间产生干扰。也可能会发生前景中的像素被分配给背景的集群beacuase它具有与背景类似的颜色。为防止这种情况发生,您可以使用this approach或region grwoth algorithm。之后,您可以让用户通过触摸选择群集并将其删除。我的Android应用程序也遇到了同样的问题。这将为您提供一个良好的开端,一旦您实现了custering, 就需要重新设置群集的 k 参数以获得良好的结果。
答案 1 :(得分:0)
似乎是一项艰巨的任务。如果您正在谈论图像处理,如果我理解,那么您可以尝试https://developers.google.com/appengine/docs/java/images/ 此外,如果你想掩盖整个背景(我还没有尝试粘贴)应用程序需要了解背景图像映射。请提供一些示例,以便我能够提出更明确的答案
答案 2 :(得分:0)
如果您在Android中工作,您可能需要一个缓冲区来从图像中获取像素 - 它是一个intBuffer并且它极大地减少了内存使用...从中获取数据并将数据存储到您拥有的缓冲区中三种方法(如果你没有'大图像,你可以跳过那部分):
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)...
答案 3 :(得分:0)
一种可能性是在openCV库中使用floodfill操作。有很多关于如何根据需要进行类似操作的示例和教程,OpenCV已移植到Android。 Google的相关条款当然是“openCV”和“floodfill”。
答案 4 :(得分:0)
对于这种任务(和应用程序),您必须使用openGL。通常在处理openGL时,您将片段着色器基于您在Matlab中构建的模块。一旦你有了片段着色器,就很容易将它应用到图像上。检查this指南如何操作。
这里是link to remove background from image in 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);
答案 5 :(得分:0)
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
希望这会对你有所帮助