반응형

안녕하세요

 

이번 OpenCvSharp를 이용한 포스팅에서 다룰 연산은 모폴로지 연산 입니다

 

모폴로지는 영상이나 이미지의 화소값을 이용하여 이미지의 형태학적 작업을 할 수 있습니다

 

[*모폴로지 연산의 종류와 간단한 설명]

  1. 팽장(Dilate)
    - 255값의 화소가 부풀어서 커지는것
  2. 침식(Erode)
    - 255값의 화소가 깎이는 것
  3. 열기연산(Opening)
    -작은 흰 점들을 없앤 뒤 큰 덩어리들은 다시 원래 크기로 키우는 연산
  4. 닫기연산(Closing)
    - 약간 떨어진 선이나 공간을 잇거나 채우고 난 뒤 전체 크기를 원래대로 줄이는 연산
  5. 그라디언트연산(Gradient)
    - 영역의 외곽선만 남기는 효과를 주는 연산
  6. 탑햇연산(TopHat)
    - 열기연산(Opening)이 수행된 부분을 빼내는 연산
  7. 블랙연산(BalckHat)
    - 원본 이미지에서 어두운 영역을 강조하는 연산

역시 영상, 이미지 분야는 어려운거 같다 모두 수학적 공식을 통해 색상을 조절하고 세밀한 조절을 통해

 

이미지나 영상의 효과나 처리를 주는데 비전공자로써는 도저히 이해가 되질 않는다ㅎ

 

나는 나의 전공으로 돌아와서 코딩을 해보겠다ㅋㅋ

 

이번 포스팅도 저번 포스팅에 이어 진행되므로 이전 포스팅을 읽고 진행 하는것이

 

이해가 빠를것이다

 

https://codingman.tistory.com/62

 

[C#] OpenCvSharp 이미지 옵티컬플로우 처리하기

안녕하세요 이번 포스팅은 OpenCvSharp로 이미지 옵티컬플로우 처리를 해보도록 하겠습니다 일단 옵티컬플로우가 무엇인지 알아야 이해가 빠를거 같은데요 저도 배우고 있는 단계라 정확한 정의는 못 내리겠습니다..

codingman.tistory.com

 

모폴로지 연산처리를 위해 Menu에 버튼을 생성한다

 

[디자인]

- 알고리즘 항목에 모폴로지를 만들고 세부 메뉴로 아래 리스트별로 생성 시킨다

 

- 세부 메뉴로 생성된 모폴로지 연산 처리별 클릭 이벤트 생성

 

[Source Code]

- 이벤트별 클래스 호출 코딩을 작성해 준다

        private void dilateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (Morphology Mp = new Morphology())
            using (IplImage temp = Mp.DilateMorphology(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;
        }

        private void erodeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (Morphology Mp = new Morphology())
            using (IplImage temp = Mp.ErodeMorphology(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;
        }

        private void openingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (Morphology Mp = new Morphology())
            using (IplImage temp = Mp.OpenMorphology(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;
        }

        private void closingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (Morphology Mp = new Morphology())
            using (IplImage temp = Mp.CloseMorphology(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;
        }

        private void gradientToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (Morphology Mp = new Morphology())
            using (IplImage temp = Mp.GradientMorphology(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;
        }

        private void topHatToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (Morphology Mp = new Morphology())
            using (IplImage temp = Mp.TopHatMorphology(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;
        }

        private void balckHatToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (Morphology Mp = new Morphology())
            using (IplImage temp = Mp.BlackHatMorphology(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;
        }

 

- 모폴로지 클래스 파일 생성

  (클래스명칭 : Morphology.cs)

 

[Source Code]

- 생성한 클래스 파일에 다음과 같으 코딩 한다

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

namespace OpenCV_V1
{
    class Morphology : IDisposable
    {
        IplImage morph;


        public IplImage DilateMorphology(IplImage src)
        {
            // 구조 요소를 지정하고, 확장 모폴로지 연산을 행한다

            //(1) 화상 읽어들여, 연산 결과 화상 영역의 확보를 행한다
            using (IplImage srcImg = src.Clone())
            using (IplImage dstImg = srcImg.Clone())
            using (IplImage tmpImg = srcImg.Clone())
            {
                //(2) 구조 요소를 생성한다 
                IplConvKernel element = Cv.CreateStructuringElementEx(9, 9, 4, 4, ElementShape.Rect, null);
                //(3) 모폴로지 연산을 실행한다 
                Cv.Dilate(srcImg, dstImg, element, 1);
                morph = dstImg.Clone();

            }
            return morph;
        }

        public IplImage ErodeMorphology(IplImage src)
        {

            // 구조 요소를 지정하고, 축소 모폴로지 연산을 행한다

            //(1) 화상 읽어들여, 연산 결과 화상 영역의 확보를 행한다
            using (IplImage srcImg = src.Clone())
            using (IplImage dstImg = srcImg.Clone())
            using (IplImage tmpImg = srcImg.Clone())
            {
                //(2) 구조 요소를 생성한다 
                IplConvKernel element = Cv.CreateStructuringElementEx(9, 9, 4, 4, ElementShape.Rect, null);
                //(3) 모폴로지 연산을 실행한다 
                Cv.Erode(srcImg, dstImg, element, 1);
                morph = dstImg.Clone();
            }
            return morph;
        }

        public IplImage OpenMorphology(IplImage src)
        {

            // 구조 요소를 지정하고, 오픈 모폴로지 연산을 행한다

            //(1) 화상 읽어들여, 연산 결과 화상 영역의 확보를 행한다
            using (IplImage srcImg = src.Clone())
            using (IplImage dstImg = srcImg.Clone())
            using (IplImage tmpImg = srcImg.Clone())
            {
                //(2) 구조 요소를 생성한다 
                IplConvKernel element = Cv.CreateStructuringElementEx(9, 9, 4, 4, ElementShape.Rect, null);
                //(3) 모폴로지 연산을 실행한다 
                Cv.MorphologyEx(srcImg, dstImg, tmpImg, element, MorphologyOperation.Open, 1);
                morph = dstImg.Clone();

            }
            return morph;
        }

        public IplImage CloseMorphology(IplImage src)
        {

            // 구조 요소를 지정하고, 닫힘 모폴로지 연산을 행한다

            //(1) 화상 읽어들여, 연산 결과 화상 영역의 확보를 행한다
            using (IplImage srcImg = src.Clone())
            using (IplImage dstImg = srcImg.Clone())
            using (IplImage tmpImg = srcImg.Clone())
            {
                //(2) 구조 요소를 생성한다 
                IplConvKernel element = Cv.CreateStructuringElementEx(9, 9, 4, 4, ElementShape.Rect, null);
                //(3) 모폴로지 연산을 실행한다 
                Cv.MorphologyEx(srcImg, dstImg, tmpImg, element, MorphologyOperation.Close, 1);
                morph = dstImg.Clone();

            }
            return morph;
        }

        public IplImage GradientMorphology(IplImage src)
        {

            // 구조 요소를 지정하고, 그라디언트 모폴로지 연산을 행한다

            //(1) 화상 읽어들여, 연산 결과 화상 영역의 확보를 행한다
            using (IplImage srcImg = src.Clone())
            using (IplImage dstImg = srcImg.Clone())
            using (IplImage tmpImg = srcImg.Clone())
            {
                //(2) 구조 요소를 생성한다 
                IplConvKernel element = Cv.CreateStructuringElementEx(9, 9, 4, 4, ElementShape.Rect, null);
                //(3) 모폴로지 연산을 실행한다 
                Cv.MorphologyEx(srcImg, dstImg, tmpImg, element, MorphologyOperation.Gradient, 1);
                morph = dstImg.Clone();
            }
            return morph;
        }

        public IplImage TopHatMorphology(IplImage src)
        {

            // 구조 요소를 지정하고, 탑햇 모폴로지 연산을 행한다

            //(1) 화상 읽어들여, 연산 결과 화상 영역의 확보를 행한다
            using (IplImage srcImg = src.Clone())
            using (IplImage dstImg = srcImg.Clone())
            using (IplImage tmpImg = srcImg.Clone())
            {
                //(2) 구조 요소를 생성한다 
                IplConvKernel element = Cv.CreateStructuringElementEx(9, 9, 4, 4, ElementShape.Rect, null);
                //(3) 모폴로지 연산을 실행한다 
                Cv.MorphologyEx(srcImg, dstImg, tmpImg, element, MorphologyOperation.TopHat, 1);
                morph = dstImg.Clone();
            }
            return morph;
        }

        public IplImage BlackHatMorphology(IplImage src)
        {

            // 구조 요소를 지정하고, 블랙햇 모폴로지 연산을 행한다

            //(1) 화상 읽어들여, 연산 결과 화상 영역의 확보를 행한다
            using (IplImage srcImg = src.Clone())
            using (IplImage dstImg = srcImg.Clone())
            using (IplImage tmpImg = srcImg.Clone())
            {
                //(2) 구조 요소를 생성한다 
                IplConvKernel element = Cv.CreateStructuringElementEx(9, 9, 4, 4, ElementShape.Rect, null);
                //(3) 모폴로지 연산을 실행한다 
                Cv.MorphologyEx(srcImg, dstImg, tmpImg, element, MorphologyOperation.BlackHat, 1);
                morph = dstImg.Clone();
            }
            return morph;
        }

        public void Dispose()
        {
            if (morph != null) Cv.ReleaseImage(morph);
        }
    }
}

 

[결과 창]

*팽창 연산 결과 화면

 

*침식 연산 결과 화면

 

* 열기 연산 결과 화면

 

* 닫기 연산 결과 화면

 

*그라디언트연산 결과 화면

 

*탑햇 연산 결과 화면

 

*블랙햇 연산 결과 화면

 

각 결과 화면을 보면 모폴로지 연산별 차이를 확인 할 수 있습니다

반응형
반응형

안녕하세요

 

이번 포스팅은 저번 포스팅(코너검출)에 이어 직선을 검출하는 기능을 구현해 보도록 하겠습니다

 

저번 포스팅에 대한 정보를 확인하고자 한다면  아래의 링크를 확인하시기 바랍니다

 

https://codingman.tistory.com/60

 

[C#] OpenCvSharp 이미지 코너 검출하기

안녕하세요 이번 포스팅은 불러온 이미지에서 CornerMinEigenVal을 이용한 코너 검출 그리고 CornerHarris를 이용한 코너 검출을 포스팅 해볼려고 합니다 일단 포스팅을 읽기에 앞서 OpenCvSharp에 대해서 공부하..

codingman.tistory.com

이번 포스팅에서는 직선 검출을 해볼껀데요

 

OpenCv에서 직선 검출시 사용할 함수는 바로 HoughLines2()함수 입니다

 

[함수 설명]

C# : public CvSeq HoughLines2(CvMat lineStorage, HoughLinesMethod method, double rho, double theta, int threshold, double param1, double param2);

 

  • lineStorage - 감지 된 라인의 스토리지입니다.
  • method - 허프 변환의 방법을 의미
    HoughLinesMethod.Standard : 기본 허프 변환
    HoughLinesMethod.Probabilistic : 확률적 허프변환, 전체 선이 아닌 선의 일부만 반환함. 선의 일부분은 시작점과 끝정보로 나타난다
    HoughLinesMethod.MultiScale : 기본 허프 변환에서 멀티 스케일 변형
  • rho - 필셀 단위로 나타나는 거리 값
  • theta - 라디안 단위로 나타나는 각도 값
  • threshold - 임계값, 해당 축적 값이 해당 값보다 크면 Line이 출력된다
  • param1 - 파라미터
    기본 허프 변환에서는 이 값이 사용되지 않는다
    Probabilistic 허프 변환에서는 선 길이의 최소 값을 나타낸다
    MultiScale 허프 변환에서는 거리 값에 대한 나누는 수를 의미한다
  • param2 - 파라미터
    기본 허프 변환에서는 이 값이 사용되지 않는다
    Probabilistic 허프 변환에서는 선들 사이의 최대 갭을 의미한다
    MultiScale 허프 변환에서는 각도에 대한 나누는 수를 의미한다

 

주요 함수 설명은 위와 같습니다 그럼 이제 구현을 하기 위한 디자인을 해보겟습니다

 

[디자인]

- 메인폼의 Menu트립에서 다음과 같이 디자인 합니다

 

- 해당 Menu 트립의 항목의 클릭 이벤트 설정

 

- 클릭이벤트에 다음과 같은 코딩은 합니다

 

[Source Code]

        private void 허프직선ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (hough Hg = new hough())
            using (IplImage temp = Hg.HoughLines(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;

        }

 

- 직선 검출을 위한 Class파일을 생성합니다

  (저는 Class명칭을 다음과 같이 hough.cs로 생성하엿습니다)

 

[Class Source Code]

using System;
using System.Collections.Generic;
using System.Text;
using OpenCvSharp;

namespace OpenCV_V1
{
    class hough : IDisposable
    {
        IplImage houghLine;

        public IplImage HoughLines(IplImage src)
        {
            // cvHoughLines2
            // 확률적 허프 변환을 지정해 선분의 검출을 실시한다

            // (1) 화상 읽기 
            using (IplImage srcImgStd = src.Clone())
            using (IplImage srcImgGray = new IplImage(src.Size, BitDepth.U8, 1))
            {
                Cv.CvtColor(srcImgStd, srcImgGray, ColorConversion.BgrToGray);

                // (2) 허프변환을 위한 캐니엣지 처리 
                Cv.Canny(srcImgGray, srcImgGray, 50, 200, ApertureSize.Size3);

                using (CvMemStorage storage = new CvMemStorage())
                {


                    // (3) 표준적 허프 변환에 의한 선의 검출과 검출된 선 그리기
                    CvSeq lines = srcImgGray.HoughLines2(storage, HoughLinesMethod.MultiScale, 1, Math.PI / 180, 50, 0, 0);
                    int limit = Math.Min(lines.Total, 10);
                    for (int i = 0; i < limit; i++)
                    {

                        CvLineSegmentPolar elem = lines.GetSeqElem<CvLineSegmentPolar>(i).Value;
                        float rho = elem.Rho;
                        float theta = elem.Theta;

                        double a = Math.Cos(theta);
                        double b = Math.Sin(theta);
                        double x0 = a * rho;
                        double y0 = b * rho;
                        CvPoint pt1 = new CvPoint { X = Cv.Round(x0 + 1000 * (-b)), Y = Cv.Round(y0 + 1000 * (a)) };
                        CvPoint pt2 = new CvPoint { X = Cv.Round(x0 - 1000 * (-b)), Y = Cv.Round(y0 - 1000 * (a)) };
                        srcImgStd.Line(pt1, pt2, CvColor.Red, 3, LineType.AntiAlias, 0);
                    }

                    houghLine = srcImgStd.Clone();
                }

            }
            return houghLine;
        }


        public void Dispose()
        {
            if (houghLine != null) Cv.ReleaseImage(houghLine);
        }
    }
}

 

이렇게 Class파일까지 생성한 뒤 실행해서 확인해보면 다음과 같은 결과가 나타납니다

 

[결과 창]

 

이미지에서 Line을 검출하여 표시하는데 이미지처리를 하지 않고 원본 파일에서 그냥 검출 시도를 했을 경우 

 

다음과 같이 인식율이 상당히 이상하게 나오네요

 

아마 인식율을 높이기 위해서는 이미지처리(흑백전환 및 픽셀 전환, 등)을 통해 직선을 좀 더 명확하게 

 

구별할 수 있도록 변경한 후에 처리시키는게 좋을거 같네요

반응형
반응형

안녕하세요

 

이번 포스팅은 불러온 이미지에서 CornerMinEigenVal을 이용한 코너 검출 그리고 CornerHarris를 이용한 코너 검출을

 

포스팅 해볼려고 합니다

 

일단 포스팅을 읽기에 앞서 OpenCvSharp에 대해서 공부하면서 연결해서 포스팅 중인데

 

이미지를 불러오는 방법이나 이미지 처리에 관련된 기본 포스팅은 아래 링크를 통해 확인하시기 바랍니다

 

연제성 포스팅이기 때문에 해당 본문 내용이 다소 생략될수 잇으니 양해 바랍니다

 

https://codingman.tistory.com/49

 

[C#]OpenCvSharp 라이브러리 사용하기 #1

안녕하세요 저번 포스팅에 C#으로 OpenCvSharp 라이브러리를 등록하여 구현하는 포스팅을 준비하던중에 OpenCv 3,4 버전에서 오류가 발생하는 문제가 있다는 얘길 듣고 부랴부랴 포스팅 내용을 검토해봤는데 역시..

codingman.tistory.com

포스팅에 앞서 공부한 내용을 설명하고 프로그램에 대한 부분도 설명 드리겠습니다

 

이미지 처리 기법중 여러 방식의 코너 검출이 있습니다

 

그중 OpenCv는 4가지 커널을 사용하여 코너를 검출 합니다

 

- 사각형

- 다이아몬드

- X

- 십자

이 형태의 커널들을 이용하여 팽창, 침식 시킨 후 차영상을 통해 코너를 검출한다고 합니다

 

이러한 형태를 사용하여 쉽게 코너를 검출할 수 있는 함수가 OpenCv에 존재하는데요

 

바로 goodFeaturesToTrack라는 함수 입니다

 

해당 함수의 형태는

 

C#: void GoodFeaturesToTrack(CvArr image, CvArr eigImage, CvArr tempImage, out CvPoint2D32f[] corners, ref int cornerCount, double qualityLevel, double minDistance, CvArr mask);

 

• image – 8비트, 32비트 부동소수점 단일 이미지

eigImage 이미지와 동일한 크기의 임시 부동 소수점 32 비트 이미지

tempImage eigImage 와 크기 및 형식이 다른 임시 이미지

• corners – 검출된 코너를 담을 벡터

cornerCount– 반환될 코너의 최대 개수, 만약 찾아낸 코너의 수가 더 많을 경우, 강력한 코너가 반환된다.

• qualityLevel – 코너라고 판단하기 위한 기준이 되는 최소의 값, 이 값은 최고의 minimal eigenvalue를 가지는 코너의                         quality에 곱해지며, 그 값보다 작은 quality를 갖는 코너는 코너라고 판단하지 않는다. 예를 들어,

                     최고의 minimal eigenvalue=1500 이고, qualityLevel= 0.01 이면, quality가 15보다 작은 코너는

                     무시된다.

• minDistance – 반환되는 코너 사이의 최소 유클리디안 거리

• mask – 코너를 찾을 관심영역, input과 크기가 동일해야한다..

 

이렇게 사용되어 집니다

 

그러면 우선 메인폼의 디자인부터 설정하겠습니다

 

[디자인]

  - 메인폼의 Menu트립에서 다음과 같이 디자인 합니다

  - 최상단에 알고리즘 -> 코너검출 -> EigenVal / Harris

 

   - Menu 트립에 클릭 이벤트를 생성합니다

      

 

[Source Code]

- EigenVal / Harris의 각각의 클릭 이벤트에 다음과 같은 코딩을 해줍니다

        private void eigenValToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (corner Cn = new corner())
            using (IplImage temp = Cn.EigenValCornerDetect(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;

        }
        private void harrisToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (corner Cn = new corner())
            using (IplImage temp = Cn.HarrisCornerDetect(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;

        }

 

- 코너 검출을 위한 Class 생성

  (클래스명징은 corner로 사용하였습니다)

 

[Class Sorce Code]

- Class 생성 방법은 이전 포스팅에서 설명했기 때문에 생략하도록 하겠습니다

using System;
using System.Collections.Generic;
using System.Text;
using OpenCvSharp;

namespace OpenCV_V1
{
    class corner : IDisposable
    {
        IplImage cor;


        public IplImage EigenValCornerDetect(IplImage src)
        {
            // cvGoodFeaturesToTrack, cvFindCornerSubPix
            // 화상의 코너 검출

            int cornerCount = 150;

            using (IplImage dstImg = src.Clone())
            using (IplImage srcImgGray = new IplImage(src.Size, BitDepth.U8, 1))
            using (IplImage eigImg = new IplImage(srcImgGray.GetSize(), BitDepth.F32, 1))
            using (IplImage tempImg = new IplImage(srcImgGray.GetSize(), BitDepth.F32, 1))
            {
                Cv.CvtColor(dstImg, srcImgGray, ColorConversion.BgrToGray);

                CvPoint2D32f[] corners;
                // (1) CornerMinEigenVal를 이용한 코너 검출
                Cv.GoodFeaturesToTrack(srcImgGray, eigImg, tempImg, out corners, ref cornerCount, 0.1, 15);
                Cv.FindCornerSubPix(srcImgGray, corners, cornerCount, new CvSize(3, 3), new CvSize(-1, -1), new CvTermCriteria(20, 0.03));
                // (2) 코너 그리기
                for (int i = 0; i < cornerCount; i++)
                    Cv.Circle(dstImg, corners[i], 3, new CvColor(255, 0, 0), 2);

                cor = dstImg.Clone();

            }

            return cor;
        }

        public IplImage HarrisCornerDetect(IplImage src)
        {
            // cvGoodFeaturesToTrack, cvFindCornerSubPix
            // 화상의 코너 검출

            int cornerCount = 150;

            using (IplImage dstImg = src.Clone())
            using (IplImage srcImgGray = new IplImage(src.Size, BitDepth.U8, 1))
            using (IplImage eigImg = new IplImage(srcImgGray.GetSize(), BitDepth.F32, 1))
            using (IplImage tempImg = new IplImage(srcImgGray.GetSize(), BitDepth.F32, 1))
            {
                Cv.CvtColor(dstImg, srcImgGray, ColorConversion.BgrToGray);

                CvPoint2D32f[] corners;



                // (1) CornerHarris를 이용한 코너 검출
                cornerCount = 150;
                Cv.GoodFeaturesToTrack(srcImgGray, eigImg, tempImg, out corners, ref cornerCount, 0.1, 15, null, 3, true, 0.01);
                Cv.FindCornerSubPix(srcImgGray, corners, cornerCount, new CvSize(3, 3), new CvSize(-1, -1), new CvTermCriteria(20, 0.03));
                // (2) 코너 그리기
                for (int i = 0; i < cornerCount; i++)
                    Cv.Circle(dstImg, corners[i], 3, new CvColor(0, 0, 255), 2);

                cor = dstImg.Clone();

            }

            return cor;
        }

        public void Dispose()
        {
            if (cor != null) Cv.ReleaseImage(cor);
        }
    }
}

 

이렇게 Class까지 생성한 다음 빌드 하여 실행 시키면 다음과 같은 결과 값을 얻을수 잇습니다

 

[결과창]

*EigenVal

*Harris

반응형
반응형

안녕하세요

 

이번 시간에는 OpenCv를 통한 이미지 회전, 축소, 확대 기능을 만들어 볼려고 합니다

 

해당 기능을 구현하기 위해서 OpenCvSharp 라이브러리 등록부터 알아봐야 하는데 

 

아래 링크를 통해 확인해 보시기 바랍니다

 

https://codingman.tistory.com/49

 

[C#]OpenCvSharp 라이브러리 사용하기 #1

안녕하세요 저번 포스팅에 C#으로 OpenCvSharp 라이브러리를 등록하여 구현하는 포스팅을 준비하던중에 OpenCv 3,4 버전에서 오류가 발생하는 문제가 있다는 얘길 듣고 부랴부랴 포스팅 내용을 검토해봤는데 역시..

codingman.tistory.com

 

그러면 해당 기능을 사용하기 위한 메뉴 등록부터 진행 하겠습니다

 

[디자인]

  - 다음과 같이 Menu에 이미지처리 -> 회전, 확대, 축소 버튼을 만들어 주세요

 

  - 각각의 버튼에 클릭이벤트를 생성해 주세요

    (이벤트 생성 방법은 여러차례 포스팅하였으므로 생략하도록 할께요)

 

[Source Code]

-회전 클릭 이벤트

        private void 회전ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (geometry Go = new geometry())
            using (IplImage temp = Go.Affine(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;

        }

 - 확대 클릭 이벤트

        private void 확대ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (geometry Go = new geometry())
            using (IplImage temp = Go.MyPyrUp(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;

        }

 

- 축소 클릭 이벤트

        private void 축소ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (geometry Go = new geometry())
            using (IplImage temp = Go.MyPyrDown(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;

        }

 

[클래스 생성]

- 이미지처리를 위한 전용 클래스 생성

 

- 클래스명은 geometry.cs로 지정하였습니다

  (클래스명은 굳이 똑같이 하지 않으셔도 됩니다)

 

 

[Source Code]

using System;
using System.Collections.Generic;
using System.Text;
using OpenCvSharp;

namespace OpenCV_V1
{
    class geometry : IDisposable
    {
        IplImage geo;

        #region Affine 변환
        //어파인 변환
        public IplImage Affine(IplImage src)
        {
            // cvGetAffineTransform + cvWarpAffine
            // 화상상의 3점에 대응하는 Affine 변환 행렬을 계산, 그 행렬을 이용하여 화상 전체의 Affine 변환을 실시한다.

            // (1) 화상을 읽어들이고, 출력용 화상의 메모리를 확보한다
            using (IplImage srcImg = src.Clone())
            using (IplImage dstImg = srcImg.Clone())
            {
                // (2) 삼각형의 회전전과 회전 후의 대응하는 정점을 각각 세트 해  
                //    cvGetAffineTransform를 이용해 Affine 행렬을 구한다  
                CvPoint2D32f[] srcPnt = new CvPoint2D32f[3];
                CvPoint2D32f[] dstPnt = new CvPoint2D32f[3];
                srcPnt[0] = new CvPoint2D32f(200.0f, 200.0f);
                srcPnt[1] = new CvPoint2D32f(250.0f, 200.0f);
                srcPnt[2] = new CvPoint2D32f(200.0f, 100.0f);
                dstPnt[0] = new CvPoint2D32f(300.0f, 100.0f);
                dstPnt[1] = new CvPoint2D32f(300.0f, 50.0f);
                dstPnt[2] = new CvPoint2D32f(200.0f, 100.0f);
                using (CvMat mapMatrix = Cv.GetAffineTransform(srcPnt, dstPnt))
                {
                    // (3) 지정된 어파인 행렬에 의해, cvWarpAffine를 사용해 화상을 회전시킨다
                    Cv.WarpAffine(srcImg, dstImg, mapMatrix, Interpolation.Linear | Interpolation.FillOutliers, CvScalar.ScalarAll(0));

                    geo = dstImg.Clone();

                }
            }
            return geo;
        }
        #endregion

        #region PyrUpDown



        //이미지의 확대
        public IplImage MyPyrUp(IplImage src)
        {
            using (IplImage srcImg = src.Clone())
            using (IplImage dstImg = new IplImage(srcImg.Width * 2, srcImg.Height * 2, srcImg.Depth, srcImg.NChannels))
            {
                // (1) 입력 화상에 대한 화상 피라미드를 구성

                Cv.PyrUp(srcImg, dstImg, CvFilter.Gaussian5x5);
                geo = dstImg.Clone();

            }
            return geo;
        }



        //이미지의 축소

        public IplImage MyPyrDown(IplImage src)
        {
            using (IplImage srcImg = src.Clone())
            using (IplImage dstImg = new IplImage(srcImg.Width / 2, srcImg.Height / 2, srcImg.Depth, srcImg.NChannels))
            {
                // (1) 입력 화상에 대한 화상 피라미드를 구성
                Cv.PyrDown(srcImg, dstImg, CvFilter.Gaussian5x5);
                geo = dstImg.Clone();

            }
            return geo;
        }

        #endregion 

        public void Dispose()
        {
            if (geo != null) geo.Dispose();
        }
    }
}
 

[결과 창]

- 이미지 회전

 

- 이미지 축소

 

-이미지 확대

 

반응형

+ Recent posts