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

Gen*_* S. 2 svg android bitmap shape polygons

所以 - 这是我很少会问“我该怎么做”的问题之一,我实际上什么也没尝试,因为我不知道从哪里开始。

这是我的问题。

我有一张照片,我在绿色屏幕上键入了它,然后变成了一个蒙版,其中我有一些透明的像素,其余的像素是黑色的。假设这个黑色形状是照片主体的上胸部和头部。

我知道如何找到所有的黑色像素,我可以很容易地找出哪些黑色像素与透明像素相邻,这样我就可以轻松画出黑色形状的轮廓,但这就是我没有想法的地方……我该如何转换它将轮廓转换为可用作多边形的连续点数组?

Jon*_*win 5

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

将矢量轮廓转换为位图的过程称为渲染。将位图转换为轮廓的相反过程称为描摹。

适用的其他标签:遮罩、矢量图形、矢量化、矢量、跟踪、贝塞尔曲线、贝塞尔曲线……

链接:
理论 PDF Potrace:基于多边形的跟踪算法
Potrace wiki
Potrace Android 端口和前端
第一点很简单,用 alpha 替换绿屏(色键)。我将创建一个掩码,以解析为向量SVG
到目前为止我所拥有的:
图像 1是原始图像(绿屏)[色键]。 图 2绿屏替换为 Alpha 蒙版。
原来的α 图像 3轮廓框(作为带有 Alpha 的位图)图像 4蒙版。
轮廓 面具.
图 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>
Run Code Online (Sandbox Code Playgroud)


SVG 注释: SVG 中的路径具有紧凑的编码。例如,M(用于“移动到”)在初始数字 x 和 y 坐标之前,而 L(线到)在应绘制直线的点之前。其他命令字母(C、S、Q、T 和 A)位于用于绘制各种贝塞尔曲线和椭圆曲线的数据之前。Q 是二次贝塞尔曲线,Z 用于闭合路径。在所有情况下,绝对坐标在大写字母命令之后,相对坐标在等效的小写字母之后使用。

轮廓框架是一个棘手位(我发现了一些编码魔法)。它是一个位图,图像的所有白色部分都是一个 alpha。事实上,连续线轮廓框架中有几种颜色(没关系)。
(我们 [I], ;O|) 可能正在接近结点现在问题的; O))
你说:

我可以轻松地绘制黑色形状的轮廓,但这就是我没有想法的地方......我如何将该轮廓转换为可用作多边形的连续点数组?

嗯,棘手(取决于你想要什么多边形,我想象一个SVG矢量图形会给我们来自掩码位图的点序列),但它是一个封闭的连续和循环(没有孔,一条线粗),还不错。

没有外部库或依赖项。
这是changeColor()代码(Image 1Image 2):这样
调用:

Bitmap chromoBmp       = changeColor(origBmp, 0xff00FF00, 0x00000000, false, "chromo");//green to alpha
Run Code Online (Sandbox Code Playgroud)


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;
}
Run Code Online (Sandbox Code Playgroud)

还有一些非常重要的(魔术)processingBitmap_BlurContour()Image2Image3):这样
调用:

Bitmap framContourBmp  = processingBitmap_BlurContour(changedBmp, 1);//thickness of frame
Run Code Online (Sandbox Code Playgroud)


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
Run Code Online (Sandbox Code Playgroud)

制作位图蒙版(Image2Image4):

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