4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【OpenCvSharp】画像の中から四角っぽいものの角をサブピクセル精度で取得する

Posted at

これで良いのか?と言う不安もありますが、備忘録的な感じで。

最初はこう書いてみました。

using (var mat = image.ToMat())
using (var gray = mat.CvtColor(ColorConversionCodes.RGB2GRAY))
using (var bin = gray.Threshold(mythreshold, 255, ThresholdTypes.Binary))
{

    var contours = bin.FindContoursAsMat(RetrievalModes.List, ContourApproximationModes.ApproxSimple);

    var candidatre = contours
        .Select(c =>
        {
            var outputMat = new MatOfPoint();
            Cv2.ApproxPolyDP(c, outputMat, 0.01 * c.ArcLength(true), true);
            //MEMO : 角のPointコレクションと面積をペアで返します。
            return new Tuple<Point[], double>(outputMat.ToArray(), Cv2.ContourArea(c.ToArray()));
        })
        //MEMO : 面積で区切ってゴミを除去してます。
        .Where(c => c.Item2 < myMaxArea && c.Item2 > myMinArea);
    return candidatre.Select(x => x.Item1).ToArray();

}

これでMat.DrawContourすると若干ずれ(2ピクセル程度)が出てしまってました。
ApproxPolyDPで近似してるせいかな?と思いますが深く追ってません。

取り合えずoutputMatMatOfPoint2fにしたら勝手に精度上げてくれないかな?と期待したのですが、そうすると数値がおかしな値が返ってきてしまいました。
恐らく内部的に整数しか扱えないものと思われます。(これもソースは追ってません)

そもそも位置がずれてしまっているので別の手段を使った方がよさそうです。

調べてみるとこんなページが有りました。

Harrisコーナー検出

このリンク先ではサブピクセル精度のコーナー検出について触れられています。

・・・そういえばCornerSubPixなんてありましたね・・・。

と言うことで修正です。

サブピクセル精度
using (var mat = image.ToMat())
using (var gray = mat.CvtColor(ColorConversionCodes.RGB2GRAY))
using (var bin = gray.Threshold(mythreshold, 255, ThresholdTypes.Binary))
{

    var contours = bin.FindContoursAsMat(RetrievalModes.List, ContourApproximationModes.ApproxSimple);

    var candidatre = contours
        .Select(c =>
        {
            var outputMat = new MatOfPoint();
            Cv2.ApproxPolyDP(c, outputMat, 0.01 * c.ArcLength(true), true);
            var criteria = new TermCriteria(CriteriaType.Eps | CriteriaType.MaxIter, 100, 0.001);
            var corners = Cv2.CornerSubPix(gray, outputMat.Select(x => new Point2f(x.X, x.Y)).ToArray(), new Size(5, 5), new Size(-1, -1), criteria);
            //MEMO : 角のPointコレクションと面積をペアで返します。
            return new Tuple<Point2f[], double>(corners, Cv2.ContourArea(c.ToArray()));
        })
        //MEMO : 面積で区切ってゴミを除去してます。
        .Where(c => c.Item2 < myMaxArea && c.Item2 > myMinArea);
    return candidatre.Select(x => x.Item1).ToArray();

}

今回のケースではこれで結構いい感じに追従できてます。

4
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?