Python 2 + PIL、エラーなし、 313 307バイト
from Image import*
I=open(sys.argv[1])
w,h=I.size;D=I.getdata()
B={i%w+i/w*1j for i in range(w*h)if D[i]!=D[0]}
n=d=1;o=v=q=p=max(B,key=abs)
while p-w:
p+=d*1j;e=2*({p}<B)+({p+d}<B)
if e!=2:e%=2;d*=1j-e*2j;p-=d/1j**e
if abs(p-q)>5:
t=(q-v)*(p-q).conjugate();q=p;w=o
if.98*abs(t)>t.real:n+=1;v=p
print n
コマンドラインでイメージファイル名を取得し、結果をSTDOUTに出力します。
すべてのテストで正しい結果が得られ、円ではn = 28です。
説明
このアルゴリズムは、多角形の周囲を歩いて、検出された頂点の数をカウントすることで機能します(方向の変化として検出されます)。原点から最も離れたピクセルから開始しますo。これは、頂点であることが保証されているため、エッジ(つまり、前景ピクセルと背景ピクセルの境界)に隣接することが保証されています。位置p、、最新の頂点v、および最新の「チェックポイント」を追跡qしoます。これらはすべて最初はに等しくなっています。またd、現在のピクセルに対するエッジの方向を追跡します。d最初は東を指しますが、これは安全な方向です。oまたは、原点から最も遠くはないでしょう。エッジに沿って、に垂直な方向、つまり左dをd指すように、つまり時計回りに移動します。「エッジから落ちる」、つまり、pポリゴンの外側にある状況、または左のピクセル(つまりの方向d)がポリゴンの内側にある状況では、調整をp行い、dそれに応じて再開します。
たびの間の距離pと最後のチェックポイントは、q5よりも大きくなり、我々は間の頂点を引き渡すかどうかを判断しようとするqとp:私たちはとの間の角度を比較するvq(すなわち、からベクトルvへq)の一般的な方向であり、最後のチェックポイントに到達したときに歩いていたポリゴンの側面、およびqp最後のチェックポイントと現在の位置の間の変位。角度が約10°より大きい場合、ポリゴンの別の辺に沿って歩いていると判断し、頂点の数を増やしv、現在の頂点をに設定しpます。各チェックポイントで、頂点を検出したかどうかに関係なくq、最後のチェックポイントであるを更新して、p。o開始点であるに戻るまでこの方法を続け、見つかった頂点の数を返します(開始点o自体が頂点であるため、頂点カウントは最初は1であることに注意してください)。
以下の画像は、検出された頂点を示しています。p新しい頂点の位置は最適ではないため、各チェックポイントでの現在位置を取得することに注意してください。実際の頂点は、おそらく周囲に沿って最後のチェックポイント、、qおよびの間にあるためpです。ご覧のとおり、最初の頂点(通常、右下の頂点)以外のすべての頂点が少しずれています。これを修正すると、より多くのバイトがかかりますが、これはそのままで十分に機能しているようです。そうは言っても、4つのテストケースだけでオーバーフィットするのは少し難しいです。
