我有很多像以下图片(只有白色和黑色):
我最后的问题是找到匹配良好的椭圆。不幸的是,真正使用过的图像并不总是那么好看。它们可能会变形一些,这使得椭圆匹配可能更难。
我的想法是找到“断点”。我在下图中标记了它们:
也许这些点可以帮助匹配省略号。最终结果应该是这样的:
有人知道可以使用什么算法来找到这些断点吗?或者甚至更好地进行良好的椭圆匹配?
非常感谢
答案 0 :(得分:3)
采样圆周点
只需扫描图像,然后选择任何白色邻居的全黑像素。您可以通过将剩余的黑色像素重新着色为任何未使用的颜色(蓝色)来实现此目的。
完成整个图像后,您可以将内部背面从未使用的颜色(蓝色)重新着色为白色。
形成每个簇/椭圆的有序圆周点列表
只需扫描图像即可找到第一个黑色像素。然后使用A*对圆周点进行排序,并将路径存储在某个数组或列表pnt[]
中,并将其作为圆形数组处理。
找到"断点"
可以通过找到的点的邻居之间的角度的峰值来检测它们。
之类的东西float a0=atan2(pnt[i].y-pnt[i-1].y,pnt[i].x-pnt[i-1].x);
float a1=atan2(pnt[i+1].y-pnt[i].y,pnt[i+1].x-pnt[i].x);
float da=fabs(a0-a1); if (da>M_PI) da=2.0*M_PI-da;
if (da>treshold) pnt[i] is break point;
或使用在断点处斜率角度变化符号的事实:
float a1=atan2(pnt[i-1].y-pnt[i-2].y,pnt[i-1].x-pnt[i-2].x);
float a1=atan2(pnt[i ].y-pnt[i-1].y,pnt[i ].x-pnt[i-1].x);
float a2=atan2(pnt[i+1].y-pnt[i ].y,pnt[i+1].x-pnt[i ].x);
float da0=a1-a0; if (da0>M_PI) da0=2.0*M_PI-da0; if (da0<-M_PI) da0=2.0*M_PI+da0;
float da1=a2-a1; if (da1>M_PI) da1=2.0*M_PI-da1; if (da1<-M_PI) da1=2.0*M_PI+da1;
if (da0*da1<0.0) pnt[i] is break point;
适合省略号
所以如果没有发现断点,你可以将整个pnt []作为单个椭圆。例如,查找边界框。它的中心是椭圆的中心,它的大小为你提供了半轴。
如果发现断点,则首先找到整个pnt[]
的边界框,以获得半轴和中心位置区域搜索的限制。然后将pnt[]
除以断点之间的部分。将每个零件作为椭圆的单独部分处理并适合。
在所有pnt[]
部分拟合之后,检查一些椭圆是否相同,例如,如果它们与另一个椭圆重叠,它们将被分割......所以合并相同的部分(或平均值以提高精度) )。然后将所有pnt[i]
点重新着色为白色,清除pnt[]
列表并循环#2 ,直到找不到更多黑色像素。
如何根据选择点拟合椭圆?
<强>代数强>
使用椭圆方程和&#34;均匀&#34;分散已知点以形成方程组来计算椭圆参数(x0,y0,rx,ry,angle
)。
<强>几何强>
例如,如果您检测到坡度为0,90,180或270度,那么您将处于与周长的半轴交叉处。因此,如果您有两个这样的点(每个半轴一个),那么您需要进行拟合(如果它是轴对齐的椭圆)。
对于非轴对齐的椭圆,您需要有足够大的圆周部分。您可以利用边界框中心也是椭圆中心的事实。所以,如果你得到整个椭圆,你也知道中心。可以检测具有最大和最小切线变化的具有圆周的半轴交点。如果你有中心和两点你所需要的一切。如果你只有部分中心(只有x或y坐标),你可以结合更多的轴点(找到3或4)...或近似丢失的信息。
半H,V线轴也与椭圆中心相交,因此如果不是pnt[]
列表中的整个椭圆,它可用于检测它。
近似搜索
你可以遍历&#34;所有&#34;椭圆参数的可能组合在#4 中的限制范围内,并选择最接近您的点的那个。这会非常慢,所以使用二分搜索就像我的approx class之类的方法。另见
如何使用它与你的相似。
<强>混合强>
您可以结合几何和近似方法。首先通过几何方法计算出你能做到的。然后用近似搜索计算其余部分。您还可以提高找到的值的精确度。
在极少数情况下合并两个椭圆而没有断点时,拟合的椭圆将与您的点不匹配。因此,如果检测到这种情况,您必须将使用的点细分为组,直到它们符合匹配...
这就是我对此的想法:
答案 1 :(得分:2)
你可能需要这样的东西:
https://en.wikipedia.org/wiki/Circle_Hough_Transform
您的边缘点只是黑色像素,至少有一个白色4邻居。
但不幸的是,你说你的椭圆可能会“倾斜”。通用椭圆由二次方程描述,如x² + Ay² + Bxy + Cx + Dy + E = 0
B²&lt; 4A(⇒A> 0)。这意味着,与圆形问题相比,您没有3个维度而是5.这会导致Hough变换更加困难。幸运的是,您的示例表明您不需要高分辨率。
另请参阅:algorithm for detecting a circle in an image
修改强>
算法的上述想法是too optimistic,至少如果以直接的方式应用的话。好消息是,似乎两个聪明人(谢永红和强吉)已经为我们完成了这项功课:
答案 2 :(得分:1)
我不确定我是否会创建自己的算法。为什么不利用其他团队所做的工作来弄清楚位图的所有曲线拟合?
Inkscape是一个开源工具,专门用于矢量图形编辑,并具有处理光栅(位图)部分的能力。
以下链接指向Inkscape API的起点:
http://wiki.inkscape.org/wiki/index.php/Script_extensions
看起来您可以在Inkscape中编写脚本,或通过外部脚本访问Inkscape。
您也可以使用inkscape命令行界面执行零脚本操作:
Corel Draw被公认为矢量图形的首选行业解决方案,并且有一些很棒的工具可以将光栅化图像转换为矢量图像。
这是指向其API的链接:
https://community.coreldraw.com/sdk/api
这里是Corel Draw批量图像处理(非脚本解决方案)的链接:
http://howto.corel.com/en/c/Automating_tasks_and_batch-processing_images_in_Corel_PHOTO-PAINT