반응형

안녕하세요

 

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

 

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

 

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

반응형
반응형

FortiClientVPNOnlineInstaller_6.2.zip
0.34MB

안녕하세요

 

코딩연습생입니다

 

이번 포스팅은 FortiGate의 VPN, SSL 접속을 위한 FortiClient 설치 방법을 포스팅 해보겠습니다

 

다운로드 받아 그냥 설치만 하면 되는거긴 한데 FortiGate가 외국회사라 그런지 주소가 간혹 기억이 안나는 경우가

 

있어서 포스팅 하게 되었습니다

 

일단 FortiClient 다운로드 주소는 

 

https://www.forticlient.com/downloads

 

Forticlient - Next Generation Endpoint Protection

Get FortiClient 6.0 for Linux Ubuntu 16.04 or higher Red Hat, CentOS 7.4 or higher Info

www.forticlient.com

혹시 싸이트 접속이 안되시는 분들은 6.2 버전을 업로드 했으니 다운로드 받으시면 될거 같습니다

 

FortiClientVPNOnlineInstaller_6.2.zip
0.34MB

 

[설치 방법]

1.위의 싸이트 or 업로드 파일을 다운로드 받는다

  - 싸이트를 통해 다운로드 할 경우 싸이트 접속 후 해당 링크 클릭

   

 

2. FortiClientVPNOnlineInstaller_6.2 파일 실행 하기

 

3. 다음을 통한 설치 이어하기

   - Yes, I have read and accept the 체크 한 후 다음

 

 

4. 다음...다음...

 

5. 설치...설치...

 

6. 설치...설치...

 

7. 완료 후 바탕화면 아이콘 실행

 

8. FortiClient 초기 설정 화면

   - 연결이름 : 명칭

   - 설명 : 명칭에 대한 설명

   - 원격 게이트웨이 : FortiGate 접속 IP 번호

                             (기본 포트번호가 아닐 경우 사용자 정의 포트번호 체크박스 클릭 후 변경)

   - 모두 작성 한 후 저장

 

9. 정상 로그인 창

   - VPN이름 : 초기 설정창에서 지정한 명칭

   - 사용자 아이디, 비밀번호 입력후 "연결" 클릭시 VPN 연결

 

반응형
반응형

안녕하세요

 

이번 시간에는 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();
        }
    }
}
 

[결과 창]

- 이미지 회전

 

- 이미지 축소

 

-이미지 확대

 

반응형
반응형

안녕하세요

 

이번 포스팅은 OpenCvSharp을 이용한 이미지 얼굴 검출 기능 입니다

 

포스팅에 앞서 준비물이 필요합니다

 

1. haarcascade_frontalface_alt.xml 파일을 다운로드 받아 해당 Degub 폴더에 삽입해주세요.

 

haarcascade_frontalface_alt.zip
0.10MB

 

 

자 이렇게 준비물이 준비가 완료가 되셨다면 아래 단계를 따라해 주세요

 

[디자인]

  - 메뉴에 얼굴검출 메뉴를 등록해 주세요

 

[Source Code]

  - 해당 메뉴에 클릭이벤트를 기능을 만들어 주세요

        private void haar얼굴검출ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (Face FA = new Face())
            using (IplImage temp = FA.FaceDetect(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;

        }

 

그리고 클래스를 생성해 줍니다

 

[Source Code]

- 저는 클래스명을 Face로 생성하였습니다

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

namespace OpenCV_V1
{
    class Face : IDisposable
    {
        IplImage FindFace;

        public IplImage FaceDetect(IplImage src)
        {
            // CvHaarClassifierCascade, cvHaarDetectObjects
            // 얼굴을 검출하기 위해서 Haar 분류기의 캐스케이드를 이용한다

            CvColor[] colors = new CvColor[]{
                new CvColor(0,0,255),
                new CvColor(0,128,255),
                new CvColor(0,255,255),
                new CvColor(0,255,0),
                new CvColor(255,128,0),
                new CvColor(255,255,0),
                new CvColor(255,0,0),
                new CvColor(255,0,255),
            };

            const double scale = 1.04;
            const double scaleFactor = 1.139;
            const int minNeighbors = 2;

            using (IplImage img = src.Clone())
            using (IplImage smallImg = new IplImage(new CvSize(Cv.Round(img.Width / scale), Cv.Round(img.Height / scale)), BitDepth.U8, 1))
            {
                // 얼굴 검출용의 화상의 생성
                using (IplImage gray = new IplImage(img.Size, BitDepth.U8, 1))
                {
                    Cv.CvtColor(img, gray, ColorConversion.BgrToGray);
                    Cv.Resize(gray, smallImg, Interpolation.Linear);
                    Cv.EqualizeHist(smallImg, smallImg);
                }

                using (CvHaarClassifierCascade cascade = CvHaarClassifierCascade.FromFile(Application.StartupPath + "\\" + "haarcascade_frontalface_alt.xml"))
                using (CvMemStorage storage = new CvMemStorage())
                {
                    storage.Clear();

                    // 얼굴의 검출

                    CvSeq<CvAvgComp> faces = Cv.HaarDetectObjects(smallImg, cascade, storage, scaleFactor, minNeighbors, 0, new CvSize(30, 30), new CvSize(0, 0));

                    // 검출한 얼굴에 원을 그린다
                    for (int i = 0; i < faces.Total; i++)
                    {
                        CvRect r = faces[i].Value.Rect;
                        CvPoint center = new CvPoint
                        {
                            X = Cv.Round((r.X + r.Width * 0.5) * scale),
                            Y = Cv.Round((r.Y + r.Height * 0.5) * scale)
                        };
                        int radius = Cv.Round((r.Width + r.Height) * 0.25 * scale);
                        img.Circle(center, radius, colors[i % 8], 3, LineType.AntiAlias, 0);
                    }
                }
                FindFace = img.Clone();
                return FindFace;
            }
        }

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

 

[결과 창]

  - 실행하게 되면 다음과 같은 결과가 나오게 됩니다

    얼굴 인식율이 100%로는 아니지만 90%로 이상 검출이 가능한거 같네요

반응형
반응형

안녕하세요

 

이번 포스팅은 OpenCv를 통한 히스토그램을 확인 할 수 있는 히스토그램 적용하기 입니다

 

히스토그램이 뭔지 저도 잘 몰랐는데요 이번에 OpenCv를 공부하면서 생소한 이미지 관련 용어들을 많이 접하게 되네요

 

일단 구글에서 정의하는 히스토그램이란?

 

『도수 분포표의 하나. 가로축에 계급을, 세로축에 도수를 취하고, 도수 분포의 상태를 직사각형의 기둥 모양으로 나타낸 그래프. 주상 도표(柱狀圖表).』

 

이렇게 정의하고 있습니다

 

무슨말인지..도통 감이 안오는데요.. 그래서 좀 더 구체적으로 검색을 해봤습니다

 

역시 어렵네요ㅎㅎ

 

좀 더 폭풍 검색을 해서 좀 더 이해가 쉬운 포스팅을 가져 왔습니다

 

1. 히스토그램이란?

    히스토그램은 이미지를 구성하는 픽셀값 분포에 대한 그래프입니다.

    X축은 픽셀값으로 범위는 0 ~ 255 사이입니다. Y축은 이미지에서 해당 픽셀값을 가진 픽셀의 개수입니다.

    히스토그램의 왼쪽에는 가장 어두운 검은색 픽셀(0)의 갯수를 보여주며 오른쪽으로 갈 수록 밝은

    픽셀의 갯수를 보여줍니다.  

 

가장 이해가 되는 값인거 같습니다

 

여기서 X축과 Y축에 대한 이미지 설명입니다

 

 

아마 이미지의 밝기의 분포도를 보기 위한 그래프인거 같습니다

 

좀 더 자세한 부분은 다음 포스팅을 확인 하시면 좋을거 같습니다

(공개 여부를 확인하지 않고 링크한것이므로 문제가 될 시 삭제 조치 하겠습니다)

 

https://webnautes.tistory.com/1274

 

OpenCV Python 강좌 - 히스토그램(Histogram)

이미지에서 히스토그램을 구하는 방법과 응용으로 Histogram Equalization, CLAHE을 설명합니다. 다음 OpenCV Python 튜토리얼을 참고하여 강좌를 비정기적로 포스팅하고 있습니다. https://docs.opencv.org/4.0.0..

webnautes.tistory.com

 

다시 C#으로 넘어와서 OpenCv로 히스토그램을 적용시켜 보도록 하겠습니다

 

1. 메뉴 등록

 

[디자인]

  - Menu에 다음과 같이 "히스토그램" 메뉴를 등록해 주세요

 

[Source Code]

  - 클릭 이벤트 생성 후 코딩

        private void 히스토그램ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (Hist Hi = new Hist())
            using (IplImage temp = Hi.BuildHist(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;

        }

 

2. 히스토그램을 위한 클래스 생성

    - 클래스 추가 하기

      (클래스명은 임의로 설정하셔도 됩니다)

 

[Source Code]

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

namespace OpenCV_V1
{
    class Hist : IDisposable
    {
        IplImage DstHist;

        public IplImage BuildHist(IplImage src)
        {
            const int histSize = 64;
            float[] range0 = { 0, 256 };
            float[][] ranges = { range0 };

            // 화상의 읽기
            using (IplImage srcImg = new IplImage(src.Size, BitDepth.U8, 1))
            using (IplImage dstImg = new IplImage(src.Size, BitDepth.U8, 1))
            using (IplImage histImg = new IplImage(new CvSize(400, 400), BitDepth.U8, 1))
            using (CvHistogram hist = new CvHistogram(new int[] { histSize }, HistogramFormat.Array, ranges, true))
            {
                src.CvtColor(srcImg, ColorConversion.BgrToGray);
                srcImg.Copy(dstImg);

                using (CvWindow windowImage = new CvWindow("image", WindowMode.AutoSize))
                using (CvWindow windowHist = new CvWindow("histogram", WindowMode.AutoSize))
                {

                    // 트랙바가 동작되었을 때의 처리
                    CvTrackbar ctBrightness = null;
                    CvTrackbar ctContrast = null;
                    CvTrackbarCallback callback = delegate (int pos)
                    {
                        int brightness = ctBrightness.Pos - 100;
                        int contrast = ctContrast.Pos - 100;
                        // LUT의 적용
                        byte[] lut = CalcLut(contrast, brightness);
                        srcImg.LUT(dstImg, lut);
                        // 히스토그램 그리기
                        CalcHist(dstImg, hist);
                        DrawHist(histImg, hist, histSize);
                        // 윈도우에 표시
                        DstHist = histImg.Clone();
                        windowImage.ShowImage(dstImg);
                        windowHist.ShowImage(histImg);
                        dstImg.Zero();
                        histImg.Zero();
                    };

                    // 트랙바의 작성
                    ctBrightness = windowImage.CreateTrackbar("brightness", 100, 200, callback);
                    ctContrast = windowImage.CreateTrackbar("contrast", 100, 200, callback);
                    // 첫회 그리기
                    callback(0);

                    // 키 입력대기
                    Cv.WaitKey(0);
                }
                return DstHist;
            }
        }

        //contrast와 brightness의 값으로부터 LUT의 값을 계산해, byte 배열로 돌려준다
        private static byte[] CalcLut(int contrast, int brightness)
        {
            byte[] lut = new byte[256];
            /*
             * The algorithm is by Werner D. Streidt
             * (http://visca.com/ffactory/archives/5-99/msg00021.html)
             */
            if (contrast > 0)
            {
                double delta = 127.0 * contrast / 100;
                double a = 255.0 / (255.0 - delta * 2);
                double b = a * (brightness - delta);
                for (int i = 0; i < 256; i++)
                {
                    int v = Cv.Round(a * i + b);
                    if (v < 0)
                        v = 0;
                    if (v > 255)
                        v = 255;
                    lut[i] = (byte)v;
                }
            }
            else
            {
                double delta = -128.0 * contrast / 100;
                double a = (256.0 - delta * 2) / 255.0;
                double b = a * brightness + delta;
                for (int i = 0; i < 256; i++)
                {
                    int v = Cv.Round(a * i + b);
                    if (v < 0)
                        v = 0;
                    if (v > 255)
                        v = 255;
                    lut[i] = (byte)v;
                }
            }
            return lut;
        }
        //히스토그램 계산
        private static void CalcHist(IplImage img, CvHistogram hist)
        {
            hist.Calc(img);
            float minValue, maxValue;
            hist.GetMinMaxValue(out minValue, out maxValue);
            Cv.Scale(hist.Bins, hist.Bins, ((double)img.Height) / maxValue, 0);
        }
        //히스토그램 그리기
        private static void DrawHist(IplImage img, CvHistogram hist, int histSize)
        {
            img.Set(CvColor.White);
            int binW = Cv.Round((double)img.Width / histSize);
            for (int i = 0; i < histSize; i++)
            {
                img.Rectangle(
                    new CvPoint(i * binW, img.Height),
                    new CvPoint((i + 1) * binW, img.Height - Cv.Round(hist.Bins[i])),
                    CvColor.Black, -1, LineType.AntiAlias, 0
                );
            }
        }

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

 

[결과창]

반응형
반응형

안녕하세요

 

저번 시간에 이미지 소벨엣지 효과 주기를 포스팅 했었는데요

 

이어서 이번에는 이미지에 라플레스엣지 효과 주기를 포스팅 해보도록 하겠습니다

 

저번 포스팅과 연결되어 진행 되오니 아래 링크를 확인해서 저번 포스팅을 확인해 보세요

 

https://codingman.tistory.com/54

 

[C#] OpenCvSharp 소벨엣지 효과 주기

안녕하세요 저번 시간에 캐니엣지 효과 주기를 포스팅 했었는데요 이어서 이번에는 이미지에 소벨엣지 효과 주기를 포스팅 해보도록 하겠습니다 저번 포스팅과 연결되어 진행 되오니 아래 링크를 확인해서 저번 포..

codingman.tistory.com

 

[디자인]

  - Menu에 다음과 같이 필터 -> 라플레스엣지 메뉴를 등록해 줍니다

 

[Source Code]

  - 라플레스엣지 메뉴에 클릭이벤트 생성

 

 - 이벤트 위치에 다음과 같이 코딩해 줍니다

        private void 라플레스엣지ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (gray gg = new gray())
            using (IplImage temp = gg.BuildLaplace(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;
        }

 

- 그레이효과 적용시에 등록한 gray.cs 클래스 파일을 이용합니다

https://codingman.tistory.com/51

 

[C#] OpenCvSharp 그레이 효과 주기

안녕하세요 요즘 C#으로 연습중인 OpenCv에서 불러온 이미지에 전체 그레이 효과를 주는 이벤트를 제작해 보겠습니다 C#을 통해 OpenCv 라이브러리 등록방법은 아래 링크를 확인해주세요 https://codingman.tistor..

codingman.tistory.com

 

[결과 실행창]

반응형
반응형

안녕하세요

 

저번 시간에 캐니엣지 효과 주기를 포스팅 했었는데요

 

이어서 이번에는 이미지에 소벨엣지 효과 주기를 포스팅 해보도록 하겠습니다

 

저번 포스팅과 연결되어 진행 되오니 아래 링크를 확인해서 저번 포스팅을 확인해 보세요

 

https://codingman.tistory.com/53

 

[C#] OpenCvSharp 캐니엣지 효과 주기

안녕하세요 저번 시간에 이미지 이진화 효과 주기를 포스팅 했었는데요 이어서 이번에는 이미지에 캐니엣지 효과 주기를 포스팅 해보도록 하겠습니다 저번 포스팅과 연결되어 진행 되오니 아래 링크를 확인해서 저..

codingman.tistory.com

 

[디자인]

  - Menu에 다음과 같이 필터 -> 소벨엣지 메뉴를 등록해 줍니다

 

[Source Code]

  - 소벨엣지 메뉴에 클릭이벤트 생성

 - 이벤트 위치에 다음과 같이 코딩해 줍니다

        private void 소벨엣지ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (gray gg = new gray())
            using (IplImage temp = gg.BuildSobel(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;
        }

 

- 그레이효과 적용시에 등록한 gray.cs 클래스 파일을 이용합니다

https://codingman.tistory.com/51

 

[C#] OpenCvSharp 그레이 효과 주기

안녕하세요 요즘 C#으로 연습중인 OpenCv에서 불러온 이미지에 전체 그레이 효과를 주는 이벤트를 제작해 보겠습니다 C#을 통해 OpenCv 라이브러리 등록방법은 아래 링크를 확인해주세요 https://codingman.tistor..

codingman.tistory.com

 

[결과창]

반응형

+ Recent posts