OpenCV

[Unity] OpenCV+Unity 도형 감별하기

Dean83 2022. 3. 30. 14:29

사각형, 원, 별표 등 이미지에서 도형 감별하기. 사실 명확하게 그려져 있는 샘플이미지에서

정확도가 높다. 사진 등에선 정확도가 매우 떨어지기에 이미지 전처리를 잘 하여야 한다. 

 

씬 이름 : Identify_Contours_by_Shape

 

1. 기본 흐름

    - 이미지를 grayscale로 변환한다

    - threshold를 이용하여 흑백으로 변환한다. 이때 사용되는것이 임계값인데, 임계값 미만이면 0, 

       임계값 초과면 설정값으로 변경하여 흑백으로만 구분한다.

    - 흑백으로 구분된 이미지에서 외각선을 찾는다.

    - 찾은 외각선을 그리기 위해 필요한 최소의 포인트를 구해낸다

       - 즉, 찾은 외각선을 다시 그리기 위해 최소 점을 구한다. 사각형을 그리는데에는 4개의 점만 있으면 되는데
         결과값이 20개가 나왔다면, 4개로 줄이는 작업을 한다. 

    - 포인트 array 개수에 따라 삼각형, 사각형, 별 등 으로 구분을 하고, 색을 넣어서 이미지를 그린다
       - 여기서 사용되는것은 Scalar 이며, 인자값이 3개이다. RGB가 아니라 BGR이다. 

    - 그린 이미지를 화면에 표시한다. 

2. 상세
    - 이미지로딩, grayscale로 변경

Mat image = Unity.TextureToMat (this.texture);
Mat grayMat = new Mat();
Cv2.CvtColor (image, grayMat, ColorConversionCodes.BGR2GRAY);

     - 이미지를 흑백으로 변경
        - 127을 넘는 값은 255로, 그 미만은 0으로 처리한다. 

        - ThresholdType에 따라 결과가 다르다. Binary, Binaryinv, Trunc, Tozero, Tozero_inv 가 있다. 

           - Binary는 흑백으로만 구분하는것이고, Trunc 는 흑을 그라데이션 처리, 흰색은 그대로 처리

           - TopZero 는 흑은 그대로 처리, 백은 그라데이션

Mat thresh = new Mat ();

//127을 넘는 값은 255로 하고, 넘지않으면 0으로 처리함으로서 흑백으로 변환한다
//ThresholdTypes.BinaryInv 는 흑백을 0과 1로 처리한 후, 이 값을 반전시킨것을 의미한다.

Cv2.Threshold (grayMat, thresh, 127, 255, ThresholdTypes.BinaryInv);

    - 경계선 찾기 (Cv2.FindContours)
       - RetrivalModes : 경계선 찾는 방법

          - External : 가장 바깥쪽 라인만 찾기

          - List : 모든 경계선을 찾으나, 하이어라키를 구성하지 않음

          - CCOMP : 모든 경계선을 찾고, 하이어라키를 2레벨로 구성

          - TREE : 모든 경계선을 찾고 모든 하이어라키를 구성

 

        - ContourApproximationModes : 경계선을 찾을때 사용하는 근사치 방법
          - None : 모든 포인트를 저장

          - simple : 경계선을 그릴수 있는 포인트만 저장 (예 : 4각형은 4개)

          - tc89_L1, TC89_KCOS : 포인트를 찾는 알고리즘..

Point[][] contours;
HierarchyIndex[] hierarchy;
Cv2.FindContours (thresh, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone, null);


    - 찾은 경계선을 반복문을 돌리고, 각 경계선을 다시 그리고, 포인트 갯수별 도형감지 및 그리기
      - ArcLength 함수 : 경계선의 길이를 리턴. 인자값은 폐곡선인지 여부 

      - ApproxPolyDP 함수 : 경계선을 그리기 위해 필요한 최소한의 점 수를 계산한다.

        - 두번째 인자값 : 앱실론. 오차를 뜻하며, 값이 작을수록 오차범위를 줄여 원래 도형에 가깝게 그려낸다.
        - 세번째 인자값 : 폐곡선 여부를 설정한다.
      - ApproxPolyDP 의 리턴 배열의 갯수가 3개이면 3각형, 4개이면 사각형...... 으로 판별한다. 
      - DrawContours : 경계선 그리기
        - 2번째 인자값 : 그릴 경계선의 포인트 데이터
        - 3번째 인자값 : 2번째 인자값의 인덱스값 지정.
        - 마지막 인자값 : 경계선 라인 두께

double length = Cv2.ArcLength(contour, true);
Point[] approx = Cv2.ApproxPolyDP(contour, length * 0.01, true);

......

Cv2.DrawContours(image, new Point[][] {contour}, 0, color, -1);