如何从位图区域获取多边形形状

时间:2016-12-07 06:21:52

标签: android svg bitmap shape polygons

所以 - 这是一个罕见的时刻我会问"我该如何"问题我在哪里没有尝试什么,因为我不知道从哪里开始。

这是我的问题。

我有一张照片,我已经在绿屏上键入,然后变成了一个面具,我有一些透明的像素,其余的是黑色。让我们说这个黑色的形状是照片主题的上胸部和头部。

我知道如何找到所有的黑色像素,我可以很容易地找出哪些黑色像素在透明的旁边,所以我可以很容易地画出黑色形状的轮廓,但那是我用完了想法的地方。 ..如何将该轮廓转换为可用作多边形的连续点数?

1 个答案:

答案 0 :(得分:3)

  

完成了我的分析,我从掩码位图创建了一个S.V.G.矢量路径。这为您提供了轮廓框架中所有点的优化顺序路径。

     

调用将矢量轮廓转换为位图的过程   渲染。将位图转换为轮廓的相反过程是   称为追踪。

适用的其他标签:面具,矢量图形,矢量化,矢量,追踪,贝塞尔曲线,贝塞尔曲线...

链接:
THEORY PDF Potrace: a polygon-based tracing algorithm
Potrace wiki
Potrace Android port and frontend
第一位很容易,用alpha替换绿屏(chromo-key)。我将创建一个掩码,以解析为向量SVG 到目前为止我所拥有的:
图像1 是原始图像(绿色屏幕)[色键]。 图片2 绿色屏幕替换为Alpha蒙版。
original alpha 图片3 轮廓框(作为Alpha的位图)图片4 面具。
contour mask
图片5 这是轮廓作为SVG矢量文件(将以下文本保存到svg.svg文件并将其加载到浏览器中以验证它; O)[看起来像图3] )。

<svg width="320" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg" desc="Created by Jon Goodwin maskActivity version 1.1.2" >
<path desc="l 0 p 0" fill="rgb(255,255,255)" stroke="rgb(0,0,0)" stroke-width="1" opacity="1.0"
d="M 125.5 13.0 L 136.0 13.5 L 145.5 15.0 L 157.5 18.0 L 166.5 23.0 L 176.5 30.0 Q 184.4 32.1 188.0 38.5 L 196.0 50.5 Q 194.8 56.3 198.0 57.5 
L 201.5 65.0 L 205.0 73.5 L 207.0 77.5 L 207.0 84.5 L 206.5 86.0 L 210.0 88.5 L 209.0 91.5 L 215.0 93.5 Q 219.7 98.3 219.0 108.5 L 218.0 111.5 
L 218.0 120.5 L 217.0 127.5 L 216.0 129.5 Q 216.5 134.5 212.5 135.0 L 208.0 136.5 L 208.0 149.5 Q 206.8 154.3 209.0 155.5 L 210.5 162.0 
L 214.5 163.0 L 218.0 165.5 Q 219.8 168.8 224.5 169.0 L 238.5 176.0 L 250.5 184.0 L 266.5 193.0 L 278.5 200.0 L 283.5 203.0 L 295.0 212.5 
L 295.5 214.0 L 299.0 216.5 L 306.0 226.5 L 308.5 231.0 L 312.0 239.5 L 66.5 240.0 L 66.0 237.5 L 68.0 234.5 
L 69.0 227.5 Q 72.6 226.1 72.5 221.0 L 78.0 214.5 L 91.5 199.0 L 96.5 198.0 L 102.0 195.5 L 104.5 192.0 L 106.0 191.5 L 103.0 185.5 
L 101.0 180.5 Q 102.0 172.5 97.5 170.0 L 94.0 167.5 L 84.5 132.0 L 84.0 124.5 Q 84.8 120.8 82.5 120.0 Q 80.3 119.3 81.0 115.5 L 82.0 112.5 
L 81.0 109.5 L 81.0 102.5 L 82.0 99.5 L 82.0 93.5 L 81.0 89.5 L 83.0 84.5 L 81.5 85.0 Q 77.5 85.5 77.0 82.5 L 78.0 70.5 Q 77.1 62.1 80.0 57.5 
Q 77.3 56.8 78.0 52.5 Q 79.6 45.5 84.5 42.0 L 86.0 41.5 Q 85.3 37.8 87.5 37.0 L 93.5 31.0 L 95.0 30.5 L 101.5 19.0 Q 106.3 20.3 107.5 18.0 
L 111.5 17.0 L 125.5 13.0 Z" />
</svg>


关于SVG的说明: SVG中的路径具有紧凑的编码。 例如,M(用于'移动到')在初始数字x和y坐标之前 L(行到)在应该绘制一条线的点之前。 更多命令字母(C,S,Q,T和A) 在用于绘制各种贝塞尔曲线和椭圆曲线的数据之前。 Q是二次Bézier, Z用于关闭路径。在所有情况下, 绝对坐标遵循大写字母命令和 在相等的小写字母后使用相对坐标。

轮廓框是一个棘手的位(我发现了一些编码魔法)。它是一个位图,图像的所有白色部分都是ONE alpha。实际上在连续的线轮廓框架中有一些颜色(即o.k.)  (我们[I],; O |)可能接近现在问题的 nub ; O))
你说:

  

我可以很容易地画出黑色形状的轮廓,但这就是我跑的地方   出于想法...如何将大纲转换为顺序   数组可用作多边形的点?

嗯, 整蛊 (并且取决于你想要的多边形,我想象一个SVG矢量图形会给我们来自掩码位图),但它是一个封闭的连续和循环(没有孔,一行粗),也不错。

没有外部库或依赖项。
这是 changeColor() 代码(图片1 图片2 ):
像这样叫:

Bitmap chromoBmp       = changeColor(origBmp, 0xff00FF00, 0x00000000, false, "chromo");//green to alpha


private Bitmap changeColor(Bitmap src, int colorToReplace, int colorThatWillReplace, boolean not, String log) {
    int width = src.getWidth();
    int height = src.getHeight();
int[] pixels = new int[width * height];
// get pixel array from source
    src.getPixels(pixels, 0, width, 0, 0, width, height);

Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
int pixel;

 // iteration through pixels
for (int y = 0; y < height; ++y) {
    for (int x = 0; x < width; ++x) {
        // get current index in 2D-matrix
        int index = y * width + x;
        pixel = pixels[index];

        if(not == true)
        {
            if(pixel != colorToReplace)
            {
                pixels[index] = colorThatWillReplace;
            }
        }
        else
        {
            if(pixel == colorToReplace)
            {
                pixels[index] = colorThatWillReplace;
            }
        }
    }//x
}//y

bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
return bmOut;
}

一些非常重要(魔术) processingBitmap_BlurContour() Image2 Image3 ):
像这样叫:

Bitmap framContourBmp  = processingBitmap_BlurContour(changedBmp, 1);//thickness of frame


private Bitmap processingBitmap_BlurContour(Bitmap src, int blurValue){
    int width = src.getWidth();
    int height = src.getHeight();

BlurMaskFilter blurMaskFilter;
Paint paintBlur = new Paint();

Bitmap dest = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);//***VERY IMPORTANT Bitmap.Config.RGB_565 **NOT** Bitmap.Config.ARGB_8888
Canvas canvas = new Canvas(dest);

//Create background in Black
Bitmap alpha = src.extractAlpha();
paintBlur.setColor(0xFF00FF00);//green with alpha set to FF
canvas.drawBitmap(alpha, 0, 0, paintBlur);

//Create outer blur, in Black
blurMaskFilter = new BlurMaskFilter(blurValue, BlurMaskFilter.Blur.OUTER);
paintBlur.setMaskFilter(blurMaskFilter);
canvas.drawBitmap(alpha, 0, 0, paintBlur);

//Create inner blur
blurMaskFilter = new BlurMaskFilter(blurValue, BlurMaskFilter.Blur.INNER);
paintBlur.setMaskFilter(blurMaskFilter);
canvas.drawBitmap(src, 0, 0, paintBlur);

return dest;
   }//processingBitmap_BlurContour

制作位图蒙版( Image2 Image4 ):

Bitmap changedBmp = changeColor(bmp, 0,  0xff000000, true, "mask");//any col NOT trans(black) -> opaque black