web-dev-qa-db-ja.com

「エッジ検出」と「画像の輪郭」の違い

私は次のコードに取り組んでいます:

_#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;

Mat src, grey;
int thresh = 10;

const char* windowName = "Contours";

void detectContours(int,void*);

int main()
{
    src = imread("C:/Users/Public/Pictures/Sample Pictures/Penguins.jpg");

    //Convert to grey scale
    cvtColor(src,grey,CV_BGR2GRAY);

    //Remove the noise
    cv::GaussianBlur(grey,grey,Size(3,3),0);

    //Create the window
    namedWindow(windowName);

    //Display the original image
    namedWindow("Original");
    imshow("Original",src);

    //Create the trackbar
    cv::createTrackbar("Thresholding",windowName,&thresh,255,detectContours);

    detectContours(0,0);
    waitKey(0);
    return 0;

}

void detectContours(int,void*)
{
    Mat canny_output,drawing;

    vector<vector<Point>> contours;
    vector<Vec4i>heirachy;

    //Detect edges using canny
    cv::Canny(grey,canny_output,thresh,2*thresh);

    namedWindow("Canny");
    imshow("Canny",canny_output);

    //Find contours
    cv::findContours(canny_output,contours,heirachy,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE,Point(0,0));

    //Setup the output into black
    drawing = Mat::zeros(canny_output.size(),CV_8UC3);



    //Draw contours
    for(int i=0;i<contours.size();i++)
    {
        cv::drawContours(drawing,contours,i,Scalar(255,255,255),1,8,heirachy,0,Point());
    }

    imshow(windowName,drawing);

}
_

理論的には、Contoursは曲線を検出することを意味します。 _Edge detection_は、エッジの検出を意味します。上記のコードでは、Cannyを使用したエッジ検出とfindContours()による曲線検出を実行しました。結果の画像は次のとおりです

キャニー画像

enter image description here

輪郭画像

enter image description here

ご覧のとおり、違いはありません!では、これら2つの実際の違いは何ですか? OpenCVチュートリアルでは、コードのみが提供されています。 「輪郭」とは何かについての説明を見つけましたが、この問題に対処していません。

27
PeakGen

Edgesは、勾配の方向における画像勾配の極値である点として計算されます。役立つ場合は、1D関数の最小点と最大点と​​考えることができます。重要なのは、エッジピクセルはローカルな概念であるということです。つまり、隣接するピクセル間の大きな違いを指しているだけです。

Contoursは、多くの場合、エッジから取得されますが、オブジェクトの輪郭であることを目的としています。したがって、それらは閉じた曲線である必要があります。それらはboundariesと考えることができます(一部の画像処理アルゴリズムとライブラリはそれらをそのように呼び出します)。エッジから取得する場合、閉じた輪郭を取得するためにエッジを接続する必要があります。

47
sansuiso

エッジとカントリーの検索の主な違いは、エッジの検索を実行すると、出力が新しい画像になることです。この新しい(エッジ画像)画像では、エッジが強調表示されます。エッジを検出するための多くのアルゴリズムがあります wikiもご覧ください

たとえば、Sobel演算子は滑らかな「霧」の結果をもたらします。特定のケースでは、キャッチはCanny Edge Detectorを使用していることです。これは、他の検出器よりも数ステップ先に進みます。実際には、さらにエッジの洗練ステップを実行します。したがって、Canny検出器の出力は、エッジの代わりに1ピクセル幅の線を含むバイナリイメージです。

一方、Contoursアルゴリズムは任意のバイナリイメージを処理します。だから、黒い背景に白い塗りつぶされた正方形を入れると。 Contoursアルゴリズムを実行した後、白い空の正方形、境界のみが得られます。

輪郭検出のその他の追加のボーナスは、実際にポイントのセットを返すことです!これらのポイントをさらに処理するために使用できるため、これは素晴らしいことです。

特定のケースでは、両方の画像が一致するのは偶然です。それはルールではなく、あなたの場合、それはCannyアルゴリズムのユニークな特性によるものです。

8
jnovacho

輪郭は、実際には「単なる」エッジの検出以上のことができます。アルゴリズムは実際に画像のエッジを検出しますが、階層に配置します。これは、画像で検出されたオブジェクトの外側の境界線をリクエストできることを意味します。このようなことは、エッジのみをチェックする場合は(直接)不可能です。

ドキュメントで読むことができるように、輪郭は主にオブジェクト認識に使用されます。この場合、エッジ検出器はより「グローバル」な操作です。輪郭アルゴリズムが何らかの種類のエッジ検出を使用していても驚かないでしょう。

4
Nallath

輪郭の概念は、エッジデータを操作するためのツールとして使用されます。すべてのエッジが同じではありません。しかし、多くの場合、例えば単峰性の色分布(つまり1色)を持つオブジェクト、エッジは実際の輪郭(輪郭、形状)です。

  1. 曲線だけでなく、エッジマップに接続されているものを検出します。 (連結成分分析)[1]
  2. 単峰性の色分布を持つオブジェクトに役立ちます(前景マスクは簡単なしきい値で簡単に見つかります)。サンプル画像は適切ではありません。

[1]国境追跡によるデジタル化されたバイナリ画像のトポロジカル構造解析、鈴木S、1985年。

2
LovaBill