C# OpenCV 강좌 : 제 21강 - 코너 검출 (1)

   

코너 (Corner)


1 영상이나 이미지의 모서리(코너)를 검출하기 위해 사용합니다. 영상이나 이미지에서 Good Feature to Track 방법과 Harris Corner Detector 방법을 이용하여 검출 할 수 있습니다.


원본(Source, src)를 영상이나 이미지를 사용하면 됩니다.

영상 사용하기 : 3강 바로가기
이미지 사용하기 : 4강 바로가기


Good Feature to Track

Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace test
{
    class OpenCV : IDisposable
    {  
        IplImage gray;    
        IplImage corner;        
        
        public IplImage GrayScale(IplImage src)
        {
            gray = new IplImage(src.Size, BitDepth.U8, 1);
            Cv.CvtColor(src, gray, ColorConversion.BgrToGray);
            return gray;
        }
                
        public IplImage GoodFeaturesToTrack(IplImage src)
        {
            corner = new IplImage(src.Size, BitDepth.U8, 3);   
            gray = new IplImage(src.Size, BitDepth.U8, 1);
            IplImage eigImg = new IplImage(src.Size, BitDepth.U8, 1);
            IplImage tempImg = new IplImage(src.Size, BitDepth.U8, 1);
            
            Cv.Copy(src, corner);        
            gray = this.GrayScale(src);
            
            CvPoint2D32f[] corners;
            int cornerCount = 150;

            Cv.GoodFeaturesToTrack(gray, eigImg, tempImg, out corners, ref cornerCount, 0.01, 5);
            
            Cv.FindCornerSubPix(gray, corners, cornerCount, new CvSize(3, 3), new CvSize(-1, -1), new CvTermCriteria(20, 0.03));                 

            for (int i = 0; i < cornerCount; i++)
            {        
                Cv.Circle(corner, corners[i], 3, CvColor.Black, 2);       
            } 
                          
            return corner;
        }
            
        public void Dispose()
        {
            if (gray != null) Cv.ReleaseImage(gray);        
            if (corner != null) Cv.ReleaseImage(corner);        
        }
    }
}

Class Code


corner = new IplImage(src.Size, BitDepth.U8, 3);   
gray = new IplImage(src.Size, BitDepth.U8, 1);
IplImage eigImg = new IplImage(src.Size, BitDepth.U8, 1);
IplImage tempImg = new IplImage(src.Size, BitDepth.U8, 1);

코너는 8Bit 단일 채널, GrayScale 영상으로 검출합니다. 출력할 이미지인 corner와 검색할 이미지인 gray를 만듭니다. 또한, GoodFeaturesToTrack에 사용하기 위한 매개변수 이미지 eigImg, tempImg를 만들어줍니다.

Cv.Copy(src, corner);        
gray = this.GrayScale(src);

corner에 원본 이미지를 복사하여 덮어씌웁니다. grayGrayScale을 적용시킵니다.

CvPoint2D32f[] corners;
int cornerCount = 150;

corners는 검색된 코너의 벡터 값이며, cornerCount는 반환할 코너의 최대 개수입니다. 이 값 보다 더 많은 코너가 검출되면 가장 값이 높은 코너가 반환됩니다.

 Cv.GoodFeaturesToTrack(gray, eigImg, tempImg, out corners, ref cornerCount, 0.01, 5);

Cv.GoodFeaturesToTrack()를 이용하여 코너들을 검출합니다. Cv.GoodFeaturesToTrack(그레이스케일, eigImg, tempImg, 코너점, 코너의 개수, 퀄리티레벨, 최소거리)입니다.

  • qualityLevel(퀄리티레벨) : 가장 좋은 코너의 측정 값에 퀄리티레벨 수치를 곱한 값 보다 낮은 값이면 그 코너들은 무시됩니다. 만약, 가장 좋은 코너의 측정 값이 1000에 퀄리티레벨이 0.01이라면 10이하의 코너 측정값은 검출하지 않습니다.

  • minDistance(최소거리) : 검출된 코너들의 최소거리입니다. 최소거리의 이상의 값만 검출합니다. 만약 최소거리가 5라면, 최소거리가 5 이하인 값은 코너로 검출하지 않습니다.

Cv.FindCornerSubPix(gray, corners, cornerCount, new CvSize(3, 3), new CvSize(-1, -1), new CvTermCriteria(20, 0.03));

Cv.FindCornerSubPix()를 이용하여 코너점들의 위치를 수정합니다. Cv.FindCornerSubPix(그레이스케일, 코너점, 코너의 개수, win Size, zeroZone Size, 기준)입니다.

  • win Size : 검출하려는 부분의 절반 크기입니다. 만약, (3, 3) 일 경우 (3 * 2 + 1) x (3 * 2 + 1) = 7x7 의 부분을 검색합니다.

  • zeroZone Size : 검출에서 제외하려는 부분의 절반 크기입니다. win과 동일한 계산방법을 사용합니다. (-1, -1)은 검출에서 제외하려는 부분이 없음을 의미합니다.

  • Criteria(기준) : 코너 정밀화 반복작업입니다. new CvTermCriteria(maxlter, epsilon)입니다. maxlter는 입력된 수치 만큼 반복작업하며, epsilon보다 값이 낮아지면 종료합니다.

for (int i = 0; i < cornerCount; i++)
{        
    Cv.Circle(corner, corners[i], 3, CvColor.Black, 2);       
} 

for문과 Cv.Circle을 이용하여 검출된 코너점들을 corner이미지에 그립니다.

Good Feature to Track - Harris Corner Detector

Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace test
{
    class OpenCV : IDisposable
    {  
        IplImage gray;    
        IplImage corner;        
        
        public IplImage GrayScale(IplImage src)
        {
            gray = new IplImage(src.Size, BitDepth.U8, 1);
            Cv.CvtColor(src, gray, ColorConversion.BgrToGray);
            return gray;
        }
                
        public IplImage GoodFeaturesToTrack(IplImage src)
        {
            corner = new IplImage(src.Size, BitDepth.U8, 3);   
            gray = new IplImage(src.Size, BitDepth.U8, 1);
            IplImage eigImg = new IplImage(src.Size, BitDepth.U8, 1);
            IplImage tempImg = new IplImage(src.Size, BitDepth.U8, 1);
            
            Cv.Copy(src, corner);
            gray = this.GrayScale(src);
            
            CvPoint2D32f[] corners;
            int cornerCount = 150;

            Cv.GoodFeaturesToTrack(gray, eigImg, tempImg, out corners, ref cornerCount, 0.01, 5, null, 3, true, 0.01);
                    
            Cv.FindCornerSubPix(gray, corners, cornerCount, new CvSize(3, 3), new CvSize(-1, -1), new CvTermCriteria(20, 0.03));                 

            for (int i = 0; i < cornerCount; i++)
            {        
                Cv.Circle(corner, corners[i], 3, CvColor.Black, 2);       
            } 
                          
            return corner;
        }
            
        public void Dispose()
        {
            if (gray != null) Cv.ReleaseImage(gray);        
            if (corner != null) Cv.ReleaseImage(corner);        
        }
    }
}

Class Code


Cv.GoodFeaturesToTrack(gray, eigImg, tempImg, out corners, ref cornerCount, 0.01, 5, null, 3, true, 0.01);

Cv.GoodFeaturesToTrack()를 그대로 이용하여 Harris Corner Detector를 적용할 수 있습니다. Cv.GoodFeaturesToTrack()를 이용하여 코너들을 검출합니다. Cv.GoodFeaturesToTrack(그레이스케일, eigImg, tempImg, 코너점, 코너의 개수, 퀄리티레벨, 최소거리, 마스크, 블록크기, Harris 방법 사용 유/무, ksize)입니다.

  • mask(마스크) : 코너가 감지되는 영역을 지정합니다.

  • blockSize(블록크기) : 코너 계산을 위한 평균 블록의 크기입니다.

  • useHarrisDetector(Haris 방법 사용 유/무) : Harris 방법을 사용할지에 대한 bool값 입니다.

  • ksize : Harris 방법의 매개 변수입니다.

Harris Corner Detector

Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace test
{
    class OpenCV : IDisposable
    {  
        IplImage gray;    
        IplImage corner;        
                
        public IplImage GrayScale(IplImage src)
        {
            gray = new IplImage(src.Size, BitDepth.U8, 1);
            Cv.CvtColor(src, gray, ColorConversion.BgrToGray);
            return gray;
        }

        public IplImage HarrisCorner(IplImage src)
        {
            gray = new IplImage(src.Size, BitDepth.U8, 1);
            corner = new IplImage(src.Size, BitDepth.F32, 1);

            gray = this.GrayScale(src);

            Cv.CornerHarris(gray, corner, 3, ApertureSize.Size3, 0.05);

            Cv.Dilate(corner, corner);
                    
            return corner;
        }
            
        public void Dispose()
        {
            if (gray != null) Cv.ReleaseImage(gray);        
            if (corner != null) Cv.ReleaseImage(corner);        
        }
    }
}

Class Code


Cv.CornerHarris(gray, corner, 3, ApertureSize.Size3, 0.05);

Cv.CornerHarris()를 이용하여 Harris 방법을 적용합니다. CvCornerHarris(그레이스케일, 반환이미지, ApertureSize, kisze)를 사용합니다.

Cv.Dilate(corner, corner);

Cv.Dilate(corner, corner)를 이용하여 이미지에서 이웃한 화소들 중 최대 화소값으로 대체하여 선명하게 만듭니다.

Result


Good Feature to Track

2

Good Feature to Track - Harris Corner Detector

3

Harris Corner Detector

4



도움이 되셨다면 광고 클릭 부탁드립니다.

⤧  Next post C# OpenCV 강좌 : 제 22강 - 코너 검출 (2) ⤧  Previous post C# OpenCV 강좌 : 제 20강 - 윤곽선 검출