【问题标题】:How can I make transparent background of a Bitmap?如何制作位图的透明背景?
【发布时间】:2014-08-30 12:12:16
【问题描述】:

我正在开发一个模块,在该模块中我必须使位图图像的背景透明。实际上,我正在制作一个像“Stick it”这样的应用程序,通过它我们可以用任何图像制作贴纸。我不知道从哪里开始。 有人可以给我一个链接或提示吗?

原图-

使背景透明后-

这就是我想要的。

【问题讨论】:

  • 我认为你需要透明的活动
  • 我想从位图图像中剪切贴纸。不起作用 。你用过“坚持”应用吗?
  • 你想从 imageview 中剪切图像中的某些部分
  • 你可以说我想让图像中特定事物周围的每个像素颜色透明。这样我就可以找到像图片一样的贴纸了。
  • @JagveerSinghRajput,你能给我们看看你想要的效果的截图吗?有些人(比如我)从来没有用过“坚持”

标签: java android image-processing bitmap bitmapimage


【解决方案1】:

我只能就如何解决您的问题提供一些提示。您需要进行图像分割。这可以通过 k-means 算法或类似的聚类算法来实现。请参阅this 了解通过聚类进行图像分割的算法this 了解 Java 代码示例。聚类的计算在移动设备上可能非常耗时。完成聚类后,您可以使用this approach 区分背景和前景。一般来说,你所有的图片都应该有一个与前景有很大不同的背景颜色,否则集群不可能在它们之间区分。也可能发生前景内部的像素被分配给背景集群,因为它具有与背景相似的颜色。为防止这种情况发生,您可以使用this approachregion grwoth algorithm。之后,您可以让用户通过触摸选择集群并删除它们。我的 Android 应用程序也有同样的问题。这将为您提供一个良好的开端,一旦您实施了集群,您只需需要调整集群的 k 参数以获得良好的结果。

【讨论】:

    【解决方案2】:

    似乎是一项艰巨的任务。如果您在谈论图像处理,如果我可以理解,那么您可以尝试https://developers.google.com/appengine/docs/java/images/ 此外,如果您想遮盖整个背景(我没有尝试粘贴它),应用程序需要了解背景图像映射。请提供一些例子,以便我提出更明确的答案

    【讨论】:

      【解决方案3】:

      一种可能性是利用 openCV 库中的洪水填充操作。有很多示例和教程介绍了如何根据您的需要做类似的事情,并且 OpenCV 已被移植到 Android。与 Google 相关的术语当然是“openCV”和“floodfill”。

      【讨论】:

        【解决方案4】:

        对于这种任务(和应用程序),您必须使用 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】:
          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);
          

          See this

          希望对你有帮助

          【讨论】:

            【解决方案6】:

            如果您在 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();
            
            }
            

            现在您可以使用缓冲区来获取像素并根据需要修改它们...(我复制了一段代码,该代码在我的 UI 上使用了进度条,因此需要一个处理程序/进度条...当我这样做时这个我正在处理更大的图像并实现了一个图像过滤器(高斯过滤器,灰色过滤器等......只需删除不需要的东西)

            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)...

            【讨论】:

              猜你喜欢
              • 2011-03-14
              • 2023-03-23
              • 2011-06-15
              • 2022-08-02
              • 2020-03-18
              • 1970-01-01
              • 2018-10-13
              • 1970-01-01
              相关资源
              最近更新 更多