【问题标题】:how to fill color in image in particular area?如何在特定区域的图像中填充颜色?
【发布时间】:2012-02-06 17:35:48
【问题描述】:

我想为基于 Paint 的应用程序填充白色区域的颜色 所以请给我建议如何做这项工作..

【问题讨论】:

  • 看看经典的洪水填充算法:en.wikipedia.org/wiki/Flood_fill
  • 嗨,这里是 [link][1] 获取图像点。仅表示图像的实际部分并消除透明部分。但我无法限制该区域。 [1]:brownandroidattack.blogspot.com/2010/03/…
  • 非常感谢 Jave 提供关于 Floodfill 算法的信息
  • 你使用什么工具(语言、图像处理框架?)
  • @misha : 我在 Android 平台上使用 JAVA 语言..

标签: android image image-processing bitmap paint


【解决方案1】:

我找到了洪水填充算法的解决方案

private void FloodFill(Bitmap bmp, Point pt, int targetColor, int replacementColor){
Queue<Point> q = new LinkedList<Point>();
q.add(pt);
while (q.size() > 0) {
    Point n = q.poll();
    if (bmp.getPixel(n.x, n.y) != targetColor)
        continue;

    Point w = n, e = new Point(n.x + 1, n.y);
    while ((w.x > 0) && (bmp.getPixel(w.x, w.y) == targetColor)) {
        bmp.setPixel(w.x, w.y, replacementColor);
        if ((w.y > 0) && (bmp.getPixel(w.x, w.y - 1) == targetColor))
            q.add(new Point(w.x, w.y - 1));
        if ((w.y < bmp.getHeight() - 1)
                && (bmp.getPixel(w.x, w.y + 1) == targetColor))
            q.add(new Point(w.x, w.y + 1));
        w.x--;
    }
    while ((e.x < bmp.getWidth() - 1)
            && (bmp.getPixel(e.x, e.y) == targetColor)) {
        bmp.setPixel(e.x, e.y, replacementColor);

        if ((e.y > 0) && (bmp.getPixel(e.x, e.y - 1) == targetColor))
            q.add(new Point(e.x, e.y - 1));
        if ((e.y < bmp.getHeight() - 1)
                && (bmp.getPixel(e.x, e.y + 1) == targetColor))
            q.add(new Point(e.x, e.y + 1));
        e.x++;
    }
}}

在android中洪水填充:

看到这个FloodFill

【讨论】:

  • 不错但是如果我只是将此算法添加到我的Android应用程序中,如果我调用函数FloodFill(具有相应的属性),那么它会起作用吗?我应该在这个函数中给出什么属性点?
  • 感谢@Hardik,它确实是一个写得很好的算法。但对于安卓手机来说,它似乎很慢。你知道其他填水的方法吗?
  • 谁能解释一下如何提供目标颜色和替换颜色以及采用哪种格式
  • 此答案未正确定义。您必须展示如何在 Android App 中使用它的完整实现,如果适用,它会完美运行。
  • 在位图图像的情况下如何使用这种填充算法?
【解决方案2】:

这是一个使用 Python 和 OpenCV 的快速应用程序(如果你足够努力的话,应该可以在 Android 上使用):

"""Flood fills with random color on click.  Press `q' to exit."""
import cv
import sys
import random

TOL = 10
TOL_BGR = (TOL, TOL, TOL, 0)

def click(event,x,y,flags,im):
    if event == cv.CV_EVENT_LBUTTONDOWN:
        b,g,r = [ random.random() * 255 for i in range(3) ]
        cv.FloodFill(im, (x,y), (b,g,r,0), TOL_BGR, TOL_BGR)

im = cv.LoadImage(sys.argv[1], cv.CV_LOAD_IMAGE_COLOR)
cv.NamedWindow(__file__, 1)
cv.SetMouseCallback(__file__, click, im)
while True:
    cv.ShowImage(__file__, im)
    key = cv.WaitKey(33)
    if chr(key & 0xff) == 'q':
        break
cv.SaveImage('floodfill.png', im)

每次用户单击图像时,应用程序都会使用单击位置作为种子进行泛洪填充。颜色是随机挑选的。您可以通过修改 TOL(或 TOL_BGR)的值来更改公差。这是点击几下后的结果:

不管你使用什么技术,一般算法都是一样的。

【讨论】:

  • 能否把源代码发给我,这部分我看不懂
  • 不,我不会通过 codez 向您发送电子邮件。无论如何,源代码在我的答案中。如果你有什么不明白的,那么请阅读相关功能的文档——它是现成的。
  • 如果我使用 SVG 而不是普通图像,会是什么方法?
【解决方案3】:

1) 将每个颜色部分的拆分图像分开,大小与实际图像相同,其他部分是透明的。 2)在您的可绘制文件夹中拥有完整的图像,每个部分都以不同的颜色绘制 - 这只是参考图像。

3) 在框架布局中添加所有拆分的图像,并将所有拆分的初始设置为不可见并设置为仅对实际图像可见

4) 热编码从您的参考图像(步骤 2)中分割出来的每个颜色,例如 handSplitImageColor = green;

4) 为框架布局设置侦听器找出 x 和 y 位置并将 x 和 y 位置传递给您的参考图像(步骤 2)并找出该特定位置的颜色并将颜色与步骤 4 匹配,然后填充该图像中的特定内容并将该分割图像的可见性设置为真。所以只有那部分会被颜色填充,因为其他部分是透明的。

这些是我用于解决我的同类问题之一的步骤。

但我认为这不是更好的解决方案,但对我来说效果很好。

【讨论】:

    【解决方案4】:

    经过大量搜索,我想出了以下内容。 快速高效

    private void myFloodFillMethod(Point node,int targetColor, int fillColor) {
        if (targetColor != fillColor) {
            Queue<Point> queue = new LinkedList<>();
            do {
                int x = node.x;
                int y = node.y;
    
                while (x > 0 && getPixelColorFromArr(x - 1, y) == targetColor) {
                    x--;                }
                boolean spanUp = false;
                boolean spanDown = false;
    
                while (x < width && checkEquality(getPixelColorFromArr(x, y),targetColor)) {
                    setPixelColorFromArr(x, y, fillColor);
                    if (!spanUp && y > 0
                            && checkEquality(getPixelColorFromArr(x, y - 1),targetColor)) {
                        queue.add(new Point(x, y - 1));
                        spanUp = true;
                    } else if (spanUp && y > 0
                            && !checkEquality(getPixelColorFromArr(x, y - 1),targetColor)) {
                        spanUp = false;
                    }
                    if (!spanDown && y < height - 1
                            && checkEquality(getPixelColorFromArr(x, y + 1), targetColor)) {
                        queue.add(new Point(x, y + 1));
                        spanDown = true;
                    } else if (spanDown && y < height - 1
                            && !checkEquality(getPixelColorFromArr(x, y + 1),targetColor)) {
                        spanDown = false;
                    }
                    x++;
                }
    
            } while ((node = queue.poll()) != null);
        }
    
    }
    
    private boolean checkEquality(int pixelColorFromArr, int targetColor) {
        return pixelColorFromArr == targetColor;
    }
    
    void fillColorInImage(Bitmap image, Point node, int targetColor, int replacementColor){
    
        if(targetColor ==  replacementColor) return;
    
        width = image.getWidth();
        height = image.getHeight();
    
        pixelArr = new int[width*height];
    
        image.getPixels(pixelArr,0,width,0,0,width,height);
        myFloodFillMethod(node,targetColor,replacementColor);
    
        image.setPixels(pixelArr,0,width,0,0,width,height);
    
    }
    

    如何调用:

    fillColorInImage(bmp, point, targetColor, replacementColor);
    

    在哪里

    bmp是图像的位图(从图像视图中提取)

    point 是用户点击的 Point(x,y):从 event.getX() 和 event.getY() 获取它

    targetColor是点的颜色:从bitmap.getPixel()获取

    replacementColor 是您要替换的颜色

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-30
      • 1970-01-01
      • 2021-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多