Computer Vision/OpenCv

OpenCV 이미지 검출 (2)

BlackWhale 2025. 2. 12. 22:07

윤곽선 (Contour) 검출

  • Contour(윤곽선)과 Edge(가장자리)의 차이는 Segment(서로 다른 두 점을 연결하는 가장 짧은 선)의 유무
    • Edge : 필터링을 통해 가장 자리에 대한 정보만 있는 상태
    • Contour : 가장 자리 정보를 모아서 선을 이루고 특정 도형으로 분류된 상태
    • 보통 Edge 검출 후 Segmentation(픽셀을 그룹별로 분류하는 것) 을 거쳐 Contour 이미지를 생성
    • 일반적으로 Contour 작업을 거쳐야 사물 인식이 가능


윤곽선 (Contour) 계층 구조 (Hierarchy)

  • 다음 / 이전 윤곽선 = 같은 계층의 윤곽선
  • 자식 / 부모 윤곽선 = 하위 / 상위 계층의 윤곽선


윤곽선 (Contour)  그리기

  • 윤곽선 검출로 얻은 윤곽점을 이어서 선으로 그림

  • 예시 코드 1
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using OpenCvSharp;

namespace opencv_8
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : System.Windows.Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Mat src = Cv2.ImRead("F:\\pepe.jpg");
            Mat gray = new Mat();
            Mat binary = new Mat();
            Mat morp = new Mat();
            Mat image = new Mat();
            Mat dst = src.Clone();

            Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3));

            OpenCvSharp.Point[][] contours;
            HierarchyIndex[] hierarchies;

            Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
            Cv2.Threshold(gray, binary, 230, 255, ThresholdTypes.Binary);
            Cv2.MorphologyEx(binary, morp, MorphTypes.Close, kernel, new OpenCvSharp.Point(-1, -1), 2);
            Cv2.BitwiseNot(morp, image);

            Cv2.FindContours(image, out contours, out hierarchies, RetrievalModes.Tree, ContourApproximationModes.ApproxTC89KCOS);
            Cv2.DrawContours(dst, contours, -1, new Scalar(255, 0, 0), 2, LineTypes.AntiAlias, hierarchies, 3);

            for (int i = 0; i < contours.Length; i++)
            {
                for (int j = 0; j < contours[i].Length; j++)
                {
                    Cv2.Circle(dst, contours[i][j], 1, new Scalar(0, 0, 255), 3);
                }
            }

            Cv2.ImShow("dst", dst);
        }
    }
}

 


예시 코드 2)

  • 그레이 스케일 변환 후 윤곽선 검출 후 컬러 이미지 위에 그리기
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using OpenCvSharp;

namespace opencv_9
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : System.Windows.Window
    {
        public MainWindow()
        {
            InitializeComponent();
            string imgPath = "F:\\dog.jpg";
            Mat image = Cv2.ImRead(imgPath);
            // 그레이스케일 변환 (CV_8UC1 이미지만 허용)
            Mat gray = new Mat();
            Cv2.CvtColor(image, gray, ColorConversionCodes.BGR2GRAY);
            // 이미지 이진화 (Thresholding)
            Mat binary = new Mat();
            Cv2.Threshold(gray, binary, 100, 255, ThresholdTypes.Binary);
            // 윤곽선 검출 (CV_8UC1 이미지 사용)
            OpenCvSharp.Point[][] contours;
            HierarchyIndex[] hierarchy;
            Cv2.FindContours(binary, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            // 윤곽선 그리기 (컬러 이미지 위에 그리기)
            Mat contourImage = image.Clone();
            Cv2.DrawContours(contourImage, contours, -1, new Scalar(0, 0, 255), 2);
            // 결과 출력
            Cv2.ImShow("Original Image", image);
            Cv2.ImShow("Binary Image", binary);
            Cv2.ImShow("Contour Detection", contourImage);
            Cv2.WaitKey(0);
            Cv2.DestroyAllWindows();
        }
    }
}


예시 코드 3

  • 그레이 스케일 변환 후 Canny Edge 검출, 기본 Threshold 적용, Adaptive Threshold 적용 후 윤곽선 출력
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using OpenCvSharp;

namespace opencv_10
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : System.Windows.Window
    {
        public MainWindow()
        {
            InitializeComponent();
            string imgPath = "F:\\dog.jpg";
            Mat src = Cv2.ImRead(imgPath);
            Mat gray = new Mat();
            Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY); // 그레이스케일 변환
            Mat imageCanny = new Mat(), imageThresh = new Mat(), imageAdaptive = new Mat();
            // Canny 엣지 검출 적용
            Cv2.Canny(gray, imageCanny, 100, 200);
            // 기본 Threshold 적용
            Cv2.Threshold(gray, imageThresh, 127, 255, ThresholdTypes.Binary);
            // Adaptive Threshold 적용
            Cv2.AdaptiveThreshold(gray, imageAdaptive, 255,
                        AdaptiveThresholdTypes.GaussianC, ThresholdTypes.Binary, 11, 2);
            // Contour 검출
            Mat cannyContours = DrawContoursOnImage(src.Clone(), imageCanny, "Canny");
            Mat threshContours = DrawContoursOnImage(src.Clone(), imageThresh, "Threshold");
            Mat adaptiveContours = DrawContoursOnImage(src.Clone(), imageAdaptive, "Adaptive Threshold");
            // 5. 결과 출력
            Cv2.ImShow("Original Image", src);
            Cv2.ImShow("Canny Edge Detection", cannyContours);
            Cv2.ImShow("Binary Threshold", threshContours);
            Cv2.ImShow("Adaptive Threshold", adaptiveContours);
            Cv2.WaitKey();
            Cv2.DestroyAllWindows();
        }
        static Mat DrawContoursOnImage(Mat image, Mat binary, string title)
        {
            OpenCvSharp.Point[][] contours;
            HierarchyIndex[] hierarchy;
            // 컨투어 찾기
            Cv2.FindContours(binary, out contours, out hierarchy,
                        RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            // 컨투어 그리기 (초록색)
            Cv2.DrawContours(image, contours, -1, new Scalar(0, 255, 0), 2);
            // 컨투어의 좌표값을 이용하여 가장 왼쪽, 오른쪽, 위쪽, 아래쪽 점 찾기
            foreach (var contour in contours)
            {
                OpenCvSharp.Point extLeft = contour[0], extRight = contour[0],
                                extTop = contour[0], extBottom = contour[0];
                foreach (var pt in contour)
                {
                    if (pt.X < extLeft.X) extLeft = pt;
                    if (pt.X > extRight.X) extRight = pt;
                    if (pt.Y < extTop.Y) extTop = pt;
                    if (pt.Y > extBottom.Y) extBottom = pt;
                }
                // 빨간색 (왼쪽), 초록색 (오른쪽), 파란색 (위쪽), 노란색 (아래쪽) 점 표시
                Cv2.Circle(image, extLeft, 8, new Scalar(0, 0, 255), -1);
                Cv2.Circle(image, extRight, 8, new Scalar(0, 255, 0), -1);
                Cv2.Circle(image, extTop, 8, new Scalar(255, 0, 0), -1);
                Cv2.Circle(image, extBottom, 8, new Scalar(255, 255, 0), -1);
            }
            return image;
        
    }
    }
}
  • Canny Edge 검출

  • 이진 Threshold

  • Adaptive Threshold

'Computer Vision > OpenCv' 카테고리의 다른 글

OpenCV 이미지 검출 (1)  (0) 2025.02.12
Scalar와 Vector 비교  (0) 2025.02.12
OpenCV 기초 (1)  (0) 2025.02.12
OpenCV 소개 및 설치  (0) 2025.02.12
머신 비전 기초(2)  (0) 2025.02.12