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

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

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();
}
4b9b3361

Ответ 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