检测后像素轮廓object(无凸包)
Outline of pixels after detecting object (without convex hull)
想法是使用 grabcut (OpenCV) 检测矩形内的图像并使用 Direct2D 创建几何体。
我的测试图片是这样的:
执行抓剪后,生成此图像:
思路就是勾勒一下。我可以使用 opacity brush 将其从背景中排除,但我想使用几何画笔以便能够像编辑器中的所有其他选择(多边形、套索、矩形)一样在其上添加 append/widen/combine 几何图形等)。
如果我对点应用凸包算法,我得到:
这当然不适合我的情况。如何勾勒图像?
从抓取中获取图像后,我根据亮度保留点:
DWORD* pixels = ...
for (UINT y = 0; y < he; y++)
{
for (UINT x = 0; x < wi; x++)
{
DWORD& col = pixels[y * wi + x];
auto lumthis = lum(col);
if (lumthis > Lum_Threshold)
{
points.push_back({x,y});
}
}
}
然后我对Y和X上的点进行排序:
std::sort(points.begin(), points.end(), [](D2D1_POINT_2F p1, D2D1_POINT_2F p2) -> bool
{
if (p1.y < p2.y)
return true;
if ((int)p1.y == (int)p2.y && p1.x < p2.x)
return true;
return false;
});
然后,对于每一行(从顶部 Y 到底部 Y 遍历上述点数组),我为每一行创建“组”:
struct SECTION
{
float left = 0, right = 0;
};
auto findgaps = [](D2D1_POINT_2F* p,size_t n) -> std::vector<SECTION>
{
std::vector<SECTION> j;
SECTION* jj = 0;
for (size_t i = 0; i < n; i++)
{
if (i == 0)
{
SECTION jp;
jp.left = p[i].x;
jp.right = p[i].x;
j.push_back(jp);
jj = &j[j.size() - 1];
continue;
}
if ((p[i].x - jj->right) < 1.5f)
{
jj->right = p[i].x;
}
else
{
SECTION jp;
jp.left = p[i].x;
jp.right = p[i].x;
j.push_back(jp);
jj = &j[j.size() - 1];
}
}
return j;
};
我卡在这一点上了。我知道从任意一组点可以有许多多边形,但在我的例子中,这些点定义了什么是“左”,什么是“右”。我将如何从这里开始?
对于任何感兴趣的人,解决方案是 OpenCV contours. Working example here。
想法是使用 grabcut (OpenCV) 检测矩形内的图像并使用 Direct2D 创建几何体。
我的测试图片是这样的:
执行抓剪后,生成此图像:
思路就是勾勒一下。我可以使用 opacity brush 将其从背景中排除,但我想使用几何画笔以便能够像编辑器中的所有其他选择(多边形、套索、矩形)一样在其上添加 append/widen/combine 几何图形等)。
如果我对点应用凸包算法,我得到:
这当然不适合我的情况。如何勾勒图像?
从抓取中获取图像后,我根据亮度保留点:
DWORD* pixels = ...
for (UINT y = 0; y < he; y++)
{
for (UINT x = 0; x < wi; x++)
{
DWORD& col = pixels[y * wi + x];
auto lumthis = lum(col);
if (lumthis > Lum_Threshold)
{
points.push_back({x,y});
}
}
}
然后我对Y和X上的点进行排序:
std::sort(points.begin(), points.end(), [](D2D1_POINT_2F p1, D2D1_POINT_2F p2) -> bool
{
if (p1.y < p2.y)
return true;
if ((int)p1.y == (int)p2.y && p1.x < p2.x)
return true;
return false;
});
然后,对于每一行(从顶部 Y 到底部 Y 遍历上述点数组),我为每一行创建“组”:
struct SECTION
{
float left = 0, right = 0;
};
auto findgaps = [](D2D1_POINT_2F* p,size_t n) -> std::vector<SECTION>
{
std::vector<SECTION> j;
SECTION* jj = 0;
for (size_t i = 0; i < n; i++)
{
if (i == 0)
{
SECTION jp;
jp.left = p[i].x;
jp.right = p[i].x;
j.push_back(jp);
jj = &j[j.size() - 1];
continue;
}
if ((p[i].x - jj->right) < 1.5f)
{
jj->right = p[i].x;
}
else
{
SECTION jp;
jp.left = p[i].x;
jp.right = p[i].x;
j.push_back(jp);
jj = &j[j.size() - 1];
}
}
return j;
};
我卡在这一点上了。我知道从任意一组点可以有许多多边形,但在我的例子中,这些点定义了什么是“左”,什么是“右”。我将如何从这里开始?
对于任何感兴趣的人,解决方案是 OpenCV contours. Working example here。