Как получить общую площадь при рисовании на холсте андроида?

Im, используя ниже код, чтобы нарисовать линию на холсте растрового изображения, пока движение пальца коснется... здесь я опубликовал частичный код, и он отлично работает.

Как показано на рисунке ниже, черно-белое растровое изображение стирается при касании. Я сделал холст прозрачным, так что становится понятным исходный макет (цветное изображение).

Я хочу знать, сколько области стерто (например, 50% или 60% растрового изображения). Есть ли способ найти это?

enter image description here

//Erasing paint

         mDrawPaint = new Paint();
    mDrawPaint.setAntiAlias(true); 
    mDrawPaint.setDither(true);  
    mDrawPaint.setStyle(Paint.Style.STROKE); 
    mDrawPaint.setStrokeJoin(Paint.Join.ROUND);
    mDrawPaint.setStrokeCap(Paint.Cap.ROUND);
    mDrawPaint.setStrokeWidth(50); 
    mDrawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    BlurMaskFilter mBlur = new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL);
    mDrawPaint.setMaskFilter(mBlur);

private void doDraw(Canvas c) {

    c.drawBitmap(mBitmap, 0, 0,null );

}

private float mX, mY;
private static final float TOUCH_TOLERANCE = 1;

void touch_start(float x, float y) {
    mPath.reset();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
}
void touch_move(float x, float y) {
    float dx = Math.abs(x - mX);
    float dy = Math.abs(y - mY);
    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
        mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
        mX = x;
        mY = y;
    }

     canvas.drawPath(mPath, mDrawPaint ); //Erasing Black and white image

}
void touch_up() {
    mPath.lineTo(mX, mY);
    // commit the path to our offscreen
    mCanvas.drawPath(mPath, mDrawPaint);
    // kill this so we don't double draw
    mPath.reset();
}

Ответы

Ответ 1

Попробуйте использовать метод Монте-Карло, чтобы оценить процент прозрачной области. Я думаю, что это самый быстрый и простой способ сделать это. Возьмите около 50 (в зависимости от требуемой точности) случайных пикселей на маске прозрачности и проверьте их цвет. Затем выполните вычисление ans = TransparentPixelsCount/TestPixelCount.

Очень сложно вычислить квадрат пользовательских чертежей, используя координаты пути. И довольно долго, чтобы перебирать все пиксели. Итак, IMHO Monte Carlo - ваш выбор.

Ответ 2

Чтобы получить точный (и медленный) ответ, вам нужно проверить каждый пиксель и подсчитать количество прозрачных и разделить на общее количество пикселей. Если ваши требования позволяют оценить, вероятно, лучше всего пробовать изображение.

Вы можете уменьшить размер изображения и выполнить и описанную выше процедуру на меньшем изображении. Это имеет тот недостаток, что операция масштабирования может проходить через все пиксели, что замедляет работу. Я бы рекомендовал выборку сетки, она похожа на сокращение, но пропускает пиксели. В принципе, мы равномерно размещаем x выборок точек на сетке над изображением. Затем подсчитайте количество прозрачных точек выборки. Оценка прозрачного процента - это суммарные прозрачные образцы/количество прозрачных образцов. Вы можете получить разумную точность (обычно в пределах 5%) с небольшим количеством, скажем, 100 образцов. Вот функция кода, которая реализует этот метод - bm - это Bitmap и scale - количество выборок на ось, поэтому установка scale = 10 дает 100 общих выборок (сетка для выборки 10x10 по изображению).

static public float percentTransparent(Bitmap bm, int scale) {

        final int width = bm.getWidth();
        final int height = bm.getHeight();

        // size of sample rectangles
        final int xStep = width/scale;
        final int yStep = height/scale;

        // center of the first rectangle
        final int xInit = xStep/2;
        final int yInit = yStep/2;

        // center of the last rectangle
        final int xEnd = width - xStep/2;
        final int yEnd = height - yStep/2;

        int totalTransparent = 0;

        for(int x = xInit; x <= xEnd; x += xStep) {
            for(int y = yInit; y <= yEnd; y += yStep) {
                if (bm.getPixel(x, y) == Color.TRANSPARENT) {
                    totalTransparent++;
                }
            }
        }
        return ((float)totalTransparent)/(scale * scale);

    }

Для справки, медленный метод, который даст вам результаты путем подсчета каждого пикселя, приведен ниже. Его можно использовать для справки при тестировании вышеуказанной оценки.

static public float percentTransparent(Bitmap bm) {
        final int width = bm.getWidth();
        final int height = bm.getHeight();

        int totalTransparent = 0;
        for(int x = 0; x < width; x++) {
            for(int y = 0; y < height; y++) {
                if (bm.getPixel(x, y) == Color.TRANSPARENT) {
                    totalTransparent++;
                }
            }
        }
        return ((float)totalTransparent)/(width * height);

    }

Ответ 3

Другой подход к этому: вы можете рассчитать размер каждого пути, используя ComputeBounds. Тогда это должно быть просто сравнить это с размером вашего вида и решить% чертежа.

Jus вам нужно иметь в виду, что путь можно нарисовать над собой, поэтому вам нужно быть осторожным и обрабатывать это при вычислении.

Ответ 4

Сохраните все значения x и y точки в двух разных отсортированных наборах, один для x значения точки и другой для значения y для точки. Конечным значением вашей привязки будет точка (min_x, min_y) и точка (max_x, max_y).

Ответ 5

Вам нужно определить точки, лежащие внутри вытянутого многоугольника. Вот функции, которые принимают массив, содержащий всю вытащенную точку, а второй параметр - это сами точки, т.е. X, y.

// Return true if the dot { x,y } is within any of the polygons in the list

function pointInPolygons( polygons, dot )

      for (i=1, [polygons count] i++)
         {
           if (pointInPolygon( polygons[i], dot )) 
                    return true
         } 

      return false
end

// Returns true if the dot { x,y } is within the polygon 
//defined by points table { {x,y},-    --{x,y},{x,y},... }

function pointInPolygon( points, dot )
    local i, j = #points, #points
    local oddNodes = false

    for i=1, #points do
            if ((points[i].y < dot.y and points[j].y>=dot.y
                    or points[j].y< dot.y and points[i].y>=dot.y) and (points[i].x<=dot.x
                    or points[j].x<=dot.x)) then
                    if (points[i].x+(dot.y-points[i].y)/(points[j].y-points[i].y)*(points[j].x-points[i].x)<dot.x) then
                            oddNodes = not oddNodes
                    end
            end
            j = i
    end

    return oddNodes
   end