반응형

안녕하세요

 

이번 포스팅은 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

 

[결과창]

반응형
반응형

안녕하세요

 

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

 

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

 

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

 

https://codingman.tistory.com/52

 

[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.BuildCanny(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

- 위의 과정을 모두 하셨다면 프로그램 실행하시면 다음과 같은 결과창을 보실 수 있습니다

반응형
반응형

안녕하세요

 

요즘 C#으로 연습중인 OpenCv에서 불러온 이미지에 전체 그레이 효과를 주는 이벤트를 

 

제작해 보겠습니다

 

C#을 통해 OpenCv 라이브러리 등록방법은 아래 링크를 확인해주세요

https://codingman.tistory.com/49

 

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

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

codingman.tistory.com

 

그다음 C#을 통해 OpenCv 그림박스에 이미지 불러오기는 아래 링크를 확인해 주세요

https://codingman.tistory.com/48

 

[C#] OpenCvSharp 이미지 읽어 오기

안녕하세요 코딩하는남자 코딩연습생입니다 저번 블로그에서 C#에서 OpenCv라이브러리 등록을 통한 도구항목 추가에 대해서 공유했었는데요 혹시 처음 오신분은 아래 링크에서 확인하시기 바랍니다 https://coding..

codingman.tistory.com

 

이렇게 위의 과정을 모두 이해하셨다면 이제 이어서 불러온 이미지에 그레이 효과를 넣어보도록 하겠습니다

 

[디자인]

미리 만들어 놓은 MenuStepmenuStrip에 필터 -> 그레이라는 메뉴를 등록합니다

 

[Source Code]

-MenuStep에서 그레이 버튼을 클릭하였을때 실행될 클릭 이벤트를 생성합니다

  - 그다음 해당 클릭 이벤트에 다음과 같이 코딩 합니다

private void 그레이ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (gray gg = new gray())
            using (IplImage temp = gg.grayProcess(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;

        }

 

 - 그다음 이미지 필터 기능을 쉽게 구별할수 있도록 그레이 클레스를 생성합니다

 

 

  - 생성된 gray.cs 파일에 다음과 같이 코딩합니다

  [Source Code]

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

namespace OpenCV_V1
{
    class gray : IDisposable
    {
        IplImage subgray;

        public IplImage grayProcess(IplImage src)
        {
            subgray = new IplImage(src.Size, BitDepth.U8, 1);
            Cv.CvtColor(src, subgray, ColorConversion.BgrToGray);

            return subgray;
        }

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

        public IplImage ThresholdProcess(IplImage src)
        {
            subgray = new IplImage(src.Size, BitDepth.U8, 1);  //메모리 확보
            Cv.CvtColor(src, subgray, ColorConversion.BgrToGray); //그레이로 변환
            Cv.Smooth(subgray, subgray, SmoothType.Gaussian, 5);  //가우시안 스무스 주기
            Cv.Threshold(subgray, subgray, 120, 255, ThresholdType.Binary);  //120은 기준이 될 임계치

            return subgray;
        }

        public IplImage BuildCanny(IplImage src)
        {
            subgray = new IplImage(src.Size, BitDepth.U8, 1);  //메모리 확보
            Cv.CvtColor(src, subgray, ColorConversion.BgrToGray);   //그레이로 변환

            Cv.Canny(subgray, subgray, 80, 255);

            return subgray;
        }

        public IplImage BuildSobel(IplImage src)
        {
            subgray = new IplImage(src.Size, BitDepth.U8, 1);//메모리 확보
            Cv.CvtColor(src, subgray, ColorConversion.BgrToGray); //그레이로 변환

            Cv.Sobel(subgray, subgray, 1, 0, ApertureSize.Size3);

            return subgray;
        }

        public IplImage BuildLaplace(IplImage src)
        {
            subgray = new IplImage(src.Size, BitDepth.U8, 1);//메모리 확보
            using (IplImage temp = new IplImage(src.Size, BitDepth.S16, 1))
            using (IplImage graytemp = new IplImage(src.Size, BitDepth.U8, 1))
            {
                Cv.CvtColor(src, graytemp, ColorConversion.BgrToGray); //그레이로 변환

                Cv.Laplace(graytemp, temp);
                Cv.ConvertScaleAbs(temp, subgray);
                return subgray;
            }
        }
    }
}

 

- 이렇게 한뒤 실행하면 다음과 같은 효과를 나타낼수 있습니다

반응형

+ Recent posts