findContours()
この画像を適応的にしきい値処理して、OpenCVを使用して外側の境界線を見つけたいと思います。私が適応しきい値を使用するのは通常の理由です。大津の方法を使用しても、グローバルなしきい値処理では、画像の異なる部分間の明るさの違いを適切に補正できません。
残念ながら、アダプティブ スレッシュホールドは、太いグリッド線との交点の一部で破損を引き起こします。これは、交点のピクセルの場合、太いグリッド線が周囲の領域の大部分を占めているため、ローカルしきい値が交点のピクセルの (適度に暗い) 値よりも高くなるためです。驚くべきことに、この効果は、しきい値ウィンドウが大きい場合でもある程度保持されます。
もちろん、これにより、これらのタイプの画像で輪郭を見つけるのに適応しきい値が役に立たなくなります。ただし、接続されたエッジを考え出す点では、Canny などの他のアルゴリズムよりも全体的にはるかに優れています。
画像内のすべての 1 ピクセルおよび 2 ピクセルのギャップを手動で埋めることにより、適応しきい値処理後にエッジを再接続することができました (実際には、実行時間を節約するために縮小された画像でしきい値処理を行います。上記のフルではギャップが大きくなります) -サイズ画像)。私が使用した OpenCV コードは次のとおりです (Android バインディング用に記述)。0 は黒、-1 は白です。
private void fillGaps(Mat image) {
int size = image.rows() * image.cols();
byte[] src = new byte[size], dst = new byte[size];
image.get(0, 0, src);
int c = image.cols();
int start = 2 * c + 2;
int end = size - start;
for (int i = start; i < end; i++) {
if (src[i+1] == -1 && src[i-1] == -1 || src[i+c] == -1 && src[i-c] ==-1){
// 1-pixel gap
dst[i] = -1;
} else if (src[i+1] == 0 && src[i+2 ] == -1 && src[i-1] == -1) {
// 2-pixel horizontal gap
dst[i] = -1; dst[i+1] = -1;
} else if (src[i+c] == 0 && src[i+2*c] == -1 && src[i-c] == -1) {
// 2-pixel vertical gap
dst[i] = -1; dst[i+c] = -1;
}
}
image.put(0, 0, dst);
}
ギャップを埋める前後の縮小画像を次に示します。
これはここではかなりうまく機能しますが、大雑把な手法であり、すべてのギャップを埋めるわけではなく、グリッドを近くの他の輪郭と結合することもあります。
適応しきい値の後で切断された輪郭を回避する信頼できる方法は何ですか?