如何从位图区域获取多边形形状
How do I get a polygon shape from a bitmap area
所以 - 这是我问 "how do I" 问题的罕见情况之一,我实际上什么也没尝试,因为我不知道从哪里开始。
这是我的问题。
我有一张照片,我在绿色屏幕上进行了键控,然后变成了一个遮罩,其中有一些像素是透明的,其余的是黑色的。假设这个黑色的形状是照片主体的上胸部和头部。
我知道如何找到所有的黑色像素,我可以很容易地找出透明像素旁边的黑色像素,这样我就可以很容易地画出黑色形状的轮廓,但这就是我 运行想法...如何将该轮廓转换为可用作多边形的连续点数组?
Finished my analysis, I've created an S.V.G. vector path from a mask bitmap. This gives you an optimised sequence path of all the points in the contour frame.
The process of converting a vector outline to a bitmap is called
rendering. The converse process of turning bitmaps into outlines is
called tracing.
适用的其他标签:遮罩、矢量图形、矢量化、矢量、追踪、贝塞尔曲线、贝塞尔曲线...
链接:
THEORY PDF Potrace: a polygon-based tracing algorithm
Potrace wiki
Potrace Android port and frontend
第一点很简单,用 alpha 替换绿屏(色键)。我将创建一个掩码,以解析为向量 SVG。
到目前为止我有什么:
图像 1 是原始图像(绿屏)[chromo-key]。 图片 2 绿屏替换为 Alpha 蒙版。
Image 3 Contour Frame (as a bitmap with Alpha) Image 4 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(对于 'move to')在初始数字 x 和 y 坐标之前,并且
L(线到)在应该画线的点之前。
更多命令字母(C、S、Q、T 和 A)
在用于绘制各种贝塞尔曲线和椭圆曲线的数据之前。
Q 是二次贝塞尔曲线,
Z 用于关闭路径。在所有情况下,
绝对坐标遵循大写字母命令和
在等效的小写字母后使用相对坐标。
轮廓框架 是一个棘手的位(我发现了一些编码魔法)。它是一个位图,图像的所有白色部分都是一个 alpha。事实上,在连续的线轮廓框架中有一些颜色(即o.k。)。
(我们 [I], ;O|) 可能 approaching 现在问题的 nub ;O) )
你说:
I can easily draw an outline of the black shape but that's where I run
out of ideas... how do I transform that outline into a sequential
array of points that can be used as a polygon?
嗯,Tricky(取决于你想要什么多边形,我想 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 to 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
所以 - 这是我问 "how do I" 问题的罕见情况之一,我实际上什么也没尝试,因为我不知道从哪里开始。
这是我的问题。
我有一张照片,我在绿色屏幕上进行了键控,然后变成了一个遮罩,其中有一些像素是透明的,其余的是黑色的。假设这个黑色的形状是照片主体的上胸部和头部。
我知道如何找到所有的黑色像素,我可以很容易地找出透明像素旁边的黑色像素,这样我就可以很容易地画出黑色形状的轮廓,但这就是我 运行想法...如何将该轮廓转换为可用作多边形的连续点数组?
Finished my analysis, I've created an S.V.G. vector path from a mask bitmap. This gives you an optimised sequence path of all the points in the contour frame.
The process of converting a vector outline to a bitmap is called rendering. The converse process of turning bitmaps into outlines is called tracing.
适用的其他标签:遮罩、矢量图形、矢量化、矢量、追踪、贝塞尔曲线、贝塞尔曲线...
链接:
THEORY PDF Potrace: a polygon-based tracing algorithm
Potrace wiki
Potrace Android port and frontend
第一点很简单,用 alpha 替换绿屏(色键)。我将创建一个掩码,以解析为向量 SVG。
到目前为止我有什么:
图像 1 是原始图像(绿屏)[chromo-key]。 图片 2 绿屏替换为 Alpha 蒙版。
图片 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(对于 'move to')在初始数字 x 和 y 坐标之前,并且
L(线到)在应该画线的点之前。
更多命令字母(C、S、Q、T 和 A)
在用于绘制各种贝塞尔曲线和椭圆曲线的数据之前。
Q 是二次贝塞尔曲线,
Z 用于关闭路径。在所有情况下,
绝对坐标遵循大写字母命令和
在等效的小写字母后使用相对坐标。
轮廓框架 是一个棘手的位(我发现了一些编码魔法)。它是一个位图,图像的所有白色部分都是一个 alpha。事实上,在连续的线轮廓框架中有一些颜色(即o.k。)。
(我们 [I], ;O|) 可能 approaching 现在问题的 nub ;O) )
你说:
I can easily draw an outline of the black shape but that's where I run out of ideas... how do I transform that outline into a sequential array of points that can be used as a polygon?
嗯,Tricky(取决于你想要什么多边形,我想 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 to 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