반응형

Anaconda3에서 기본 설치시 파이선 3.7버전이 설치 되게 된다

 

하지만 텐서플로우나 특정 버전을 사용해야 할 경우 파이썬 버젼을 변경해야 하는데

 

이번 포스팅에서 Python 버전을 변경하는 방법을 설명 하도록 하겟습니다

 

1. 첫번재로 Anaconda 설치시 같이 설치 되는 명령 프롬프트를 실행 하세요

   - Anaconda Prompt 관리자 권한으로 실행 하세요

 

2. 명령 프롬프트에 다음 명령어를 실행 하세요

   - 저는 3.6버전을 설치 합니다

   - 아래 명령어를 실행하게 되면 3.6버전의 가장 마지막 버전이 설치되어 집니다

conda install python=3.6

 

3. 설치 최종 확인

    - 다음 구문이 뜨게 되면 'Y'를 입력해 주세요

 

4. 설치를 진행 합니다

    - 약간 수분이 걸릴수 있으니 'done'라는 말이 뜰때까지 기다려 주세요

 

5. 적용 버전 확인 하기

    - 아래 명령어를 실행해서 변경된 Python의 버전을 확인 합니다

python -V

반응형
반응형

안녕하세요

 

이번 시간 포스팅 내용은 텐소플로우에 모델을 추가하고 학습할수 있게 하기 위한

 

slim 라이브러리 설치 방법입니다

 

해당 포스팅을 검색해서 찾아오셨다면 이미 기본 적인 내용을 알고 오셨으리라 생각합니다

 

그럼 slim 라이브러리 설비 방법에 대해 포스팅해드리겠습니다

 

환경으로는

1)Anaconda3

2)Tensorflow 1.13.1

3)이미지모델라이브러리

 

Anaconda3 + Tensorflow 설치 방법은 저번 포스팅에 올려있으니 확인하시면 될거 같습니다

https://codingman.tistory.com/77?category=741547

 

[Deep Learning] Anaconda3 + Tensorflow 사용하기

안녕하세요 코딩연습생 입니다ㅠ 개발 블로그를 운영하면서 이것저것 많이 정보를 올리고 있는데 해보고자 하는 연습물이 잘 안풀려서 요즘 1일 1포스팅이 잘 안 이루어지고 있습니다ㅠ 대충 포스팅 글 올리기에..

codingman.tistory.com

 

그럼 이미지 모델 라이브러리 다운로드와 적용 방법에 대해 포스팅 하겠습니다

 

1. 깃헙에 가서 모델 라이브러리를 다운로드 받습니다

    (아래 링크를 클릭하면 해당 싸이트로 이동합니다)

 

https://github.com/tensorflow/models

 

tensorflow/models

Models and examples built with TensorFlow. Contribute to tensorflow/models development by creating an account on GitHub.

github.com

 

2. 다운로드 받은 모델 라이브러리 중 해당 위치의 파일을 열어 줍니다

   (Model\models-master\models-master\research\slim\download_and_convert_data.py)

   (저는 Anaconda3에 포함되어 있는 spyder를 이용해서 열었습니다)

 

 

3. download_and_convert_data.py 파일 내용중 210번 줄의 내용을 주석 처리 합니다

 

4. 파이썬의 텐서플로우를 통해 TFRecord 포멧으로 변환 해줍니다

   1) 가상환경을 활성해 해줍니다

   2) 모델 라이브러리가 설치된 경로를 지정해 줍니다

      (DOS를 사용해 보신 분이라면 명령어가 비슷해서 쉽가 하 실수 있을거 같습니다)

   3) TFRecord 생성 명령어를 실행

     

python download_and_convert_data.py --dataset_name=flowers --dataset_dir=/tmp/flowers

 

[오류 처리]

 

1. 실행 시 다음과 같은 오류가 발생할 수 있습니다

   - ModuleNotFoundError: No module named 'contextlib2'

 

그럴경우 다음 명령어를 실행해 줍니다

pip install contextlib2

 

2. 다음 오류가 발생할 수 있습니다

   - ModuleNotFoundError: No module named 'PIL'

 

 

 

다음 명령어를 실행 줍니다

 

pip install pillow

 

3. 해당 오류가 나탈날 경우 입니다

   - AttributeError: module 'tensorflow.python.util.compat' has no attribute 'v1'

 

이 경우 기존 설치된 tensorflow를 삭제하고 다운 그레이드를 해야 합니다

 

다음 명령어를 실행해 줍니다

pip uninstall tensorflow

 

다음 명령어를 실행해 줍니다

pip install tensorflow==1.13.1

 

 

TFRecord 포맷 생성 명령어를 다시 실행해 줍니다

python download_and_convert_data.py --dataset_name=flowers --dataset_dir=/tmp/flowers

 

 

다음과 같은 문구가 뜬다면 설치에 정상 성공 하신겁니다

 

"Finished converting the Flowers dataset!"

 

반응형
반응형

안녕하세요

 

코딩연습생 입니다ㅠ 개발 블로그를 운영하면서 이것저것 많이 정보를 올리고 있는데

 

해보고자 하는 연습물이 잘 안풀려서 요즘 1일 1포스팅이 잘 안 이루어지고 있습니다ㅠ

 

대충 포스팅 글 올리기에 집중하기 보단 좀 더 정확한 정보를 업로드 하고자 늦어지는것입니다

 

이번 포스팅은 Deep Learning을 구현해 볼려고 하는데요

 

Deep Learning란?

- 기계 학습 알고리즘의 집합(?)

   이런식으로 표현을 하는거 같습니다 딥러닝이라는것은 컴퓨터 비전, 머신런닝, 음성인식, 신호처리등

   모든 분야에서 기계 학습을 통한 훈련 기법 이다 라고 저는 생각합니다

 

딥러닝 기법을 사용하고자 할때 제일 많이 듣는 말이 텐서플로우(Tensorflow)인데요

 

그럼 텐서플로우는 또 뭐냐?

 

텐서플로우란?

 - 구글이 2011년에 개발을 시작하여 2015년에 오픈소스로 공개한 기계학습 라이브러리

    2016년 알파고와 함께 관심이 높아진 컨퍼런스임

    Python 언어로 되어 있는 텐서플로우는 다른 프로그래밍 언어들 연계하여 

    다양한 분야에 적용할 수 있음

 

뭐 인터넷에 이정도 포스팅 되어 있네요ㅎ

 

참 어렵습니다ㅎ

 

근데 이것을 왜 제가 하고 있는냐 단순합니다 기존 OpenCv를 통해 이미지 처리법을 공부하고

 

그 처리된 이미지를 통해 판독 시스템을 만들어볼 예정이거든요

 

근데 단순 판독이 아니라 시스템 자체 학습을 통해 신규 사물을 재정의하고 학습하면서

 

시스템에 보이는 이미지를 어떤 이미지라고 인식하는 프로그램을 만들려고 하다보니

 

이 영역까지 오게 되었습니다ㅎㅎ

 

그래서 어쨋든 핵심인 딥러닝을 구현하기 위해서는 텐서플로우가 필요하고 그 텐서플로우를 알려면

 

Python을 알아야한다는게 결론입니다

 

이래서 사설이 엄청 길어졌는데 이번 포스팅에서 윈도우에서 Python과 텐서플로우를 셋팅하는 방법을

 

포스팅 해볼려고 합니다

 

일단 윈도우에서 Python을 사용하기 위해 Anaconda라는 프로그램을 설치 할것입니다

 

1.Anaconda3 설치하기

  - 링크 주소를 통해 사이트에서 다운로드 받기

https://www.anaconda.com/distribution/

 

Anaconda Python/R Distribution - Free Download

Anaconda Distribution is the world's most popular Python data science platform. Download the free version to access over 1500 data science packages and manage libraries and dependencies with Conda.

www.anaconda.com

 

- 링크를 접속하신뒤에 Download 버튼 눌러 줍니다

 

- 적용하실려는 PC의 OS타입 그리고 OS비트에 맞는 링크를 눌러 다운로드를 실행합니다

- 다운 받은 실행 파일을 실행하여 설치를 진행해 주세요

 

 

- 경로 지정이 나올때까지 다음(Next) 버튼을 눌러주세요

 

- 경로 지정 부분이 나타나면 Default로 설치하셔도 되긴 합니다만

  기본 경로에 있는 ProgramData 폴더는 숨김 폴더라 삭제할때 조금 귀찮아 질 수 있어서

  저는 D:\에 Anaconda3라는 폴더로 지정하여 설치 하였습니다

   

 

 

- 이렇게 설치가 완료 되어지면 시작 메뉴에서 다음 메뉴를 "관리자 권한으로 실행해 주세요"

 

- 그러면 콘솔창이 하나 뜹니다 거기에 다음과 같으 명령어를 쳐주세요

 

conda upgrade pip

 

- 그 다음 pip 패키지 업데이트를 실행 합니다

pip install upgrade

 

※다음과 같은 오류가 날수가 있는데 저의 경우 패스 했습니다

 

- 다음은 텐서플로우 설치를 위한 가상환경을 만들어 줍니다

conda create -n 임의이름지정 python=3.6

 

- Proceed([y]/n)?이라고 물어보면 y를 눌러주고 엔터를 칩니다

 

 

- 생성된 가상환경을 활성화 시켜 줍니다

 

activate 지정된 임의 가상환경 이름

- 이렇게 하면 다음과 같이 (base)가 가상환경 이름으로 변경이 됩니다

 

- 그다음 텐서플로우를 설치 합니다

pip install tensorflow

 

 

- 설치가 모두 끝나고 나면 python을 실행 시켜줍니다

python

 

- 파이썬이 제대로 실행되는지 명령어를 칩니다

import tensorflow as tf
hello = tf.constant("hello, TensorFlow!")
sess = tf.Session()
print(sess.run(hello))

 

- 그런데 다음과 같은 오류가 뜨실수 있습니다

  (DLL load failed: 지정된 모듈을 찾을 수 없습니다)

 

- AVX(Advanced Vector Extensions)를 지원하지 않는 CPU를 사용할 경우 다음과 같은 오류가 납니다

 

- 이경우 텐서플로우를 다운그래이드 해줘야 합니다

 

pip install tensorflow==1.5

 

- 이렇게 다운그래이드를 실행한 다음에 다시 파이썬을 실행한뒤 명령어를 실행합니다

 

 

- 이렇게 출력이 되면 정상적으로 텐서플로우를 파이썬에서 호출해서 사용된것입니다

 

반응형
반응형

안녕하세요

 

이번 시간 포스팅 내용은 제목과 똑같이 원본이미지에서 찾고자 하는 부분이미지를 매칭하여

 

원본이미지에 해당 부분을 검출해 내는 기능입니다

 

이미 인터넷상에 많은 정보가 있기에 별도 설명은 생략하고 바로 기능 구현으로 넘어가겠습니다

 

해당 포스팅도 저번 포스팅에 이어 진행됨에 따라 내용이 중간 생략 부분이 있을 수 있으니

 

이해가 잘되시면 이전 포스팅을 검색해 보시기 바랍니다

 

https://codingman.tistory.com/49

 

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

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

codingman.tistory.com

 

템플릿 매칭을 하기 위해 두개의 이미지를 불러와야 하는데요

 

그러기 위한 디자인 UI 부터 보여드릴께요

 

[디자인]

- 메뉴에서 유틸리티 -> 템플릿매칭 버튼을 생성

 

- 해당 버튼에서 발생할 클릭 이벤트 활성화

 

- 이벤트 구문에 다음과 같이 소스 코딩 합니다

        private void 템플릿매칭ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (src == null) return;
            using (Match Sq = new Match())
            using (IplImage temp = Sq.Templit(src, src2))
            {
                result = temp.Clone();

            }

            using (CvWindow wind = new CvWindow("결과창"))
            {
                wind.Image = result;
                Cv.WaitKey(0);
            }
        }

 

- 템플릿 매칭 기능이 동작할 클래스를 하나 생성합니다

 

- 생성된 클래스에 다음과 같으 코딩합니다

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

namespace OpenCV_V1
{
    class Match : IDisposable
    {
        IplImage match;

        public IplImage Templit(IplImage src, IplImage temp)
        {
            match = src;
            IplImage templit = temp;
            IplImage tm = new IplImage(new CvSize(match.Size.Width - templit.Size.Width + 1, match.Size.Height - templit.Size.Height + 1), BitDepth.F32, 1);

            CvPoint minloc, maxloc;
            Double minval, maxval;

            Cv.MatchTemplate(match, templit, tm, MatchTemplateMethod.SqDiffNormed);

            Cv.MinMaxLoc(tm, out minval, out maxval, out minloc, out maxloc);

            Cv.DrawRect(match, new CvRect(minloc.X, minloc.Y, templit.Width, templit.Height), CvColor.Red, 3);

            return match;
        }

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

 

- 그림읽기를 통해 원본 이미지를 불러옵니다

 

- 그림읽기2를 통해 매칭 이미지를 불러옵니다

 

- 유틸리티 -> 템플릿매칭 버튼을 눌러 결과를 확인 합니다

 

[결과 창]

 

- 이렇게 매칭 이미지(쯔위)를 원본이미지에서 검출해 내는것을 확인 할 수 있습니다

 

- 프로그램을 구현하신뒤 다른 이미지로 테스트 해보시기 바랍니다

반응형
반응형

안녕하세요

 

이번 시간 포스팅할 부분은 OpenCvSharp를 이용한 PCA(Principal Component Analysis)를 구현해 볼려고 합니다

 

근데 아무 저와 똑같이 PCA가 뭐지??라는 분들이 많으실거 같아서 검색을 통해 제가 알아본 내용을

 

간략하게 소개 하고 구현 해보도록 할께요

 

▶ 주성분분석(Principal Component Analysis)

      - PCA는 분포된 데이터들의 주성분(Principal Component)를 찾아 고차원의 데이터를 저차원의 데이터로 환원

        시키는 기법

 

 

음... 정의를 보아도 무슨말인지 잘 이해가 되지 않습니다. 제가 이해한것을 표현하자면 어떤한 데이터의 주성분을

 

분석하여 데이터로 환원한뒤 그 환원된 값의 분포도에 따라 어떠한 형태를 띄고 있는지를 보는 거라고 이해하고

 

있는데 이게 맞는것인지를 모르겠습니다

 

제가 이해한 정의를 가지고 프로그래밍을 분석하여 구현하였는데

 

프로그램적 순서를 보면 이렇습니다 

 

① 원본 이미지

② 대상 이미지

③ 형상 비교를 통한 매치율 분석

 

이론은 간단하지만 구현하고 분석을 쉽지가 않더라구요 아무 저도 프로그래머다 보니 논리적 이론 보다는

 

프로그램적 구현쪽을 더 많이 파고 있는 입장이라 완벽한 설명은 불가합니다

 

좀 더 구체적 이해와 설명이 필요하시면 검색을 통해 이해 하시는게 좋을거 같습니다

 

그럼 다시 본론으로 돌아와서 프로그램 구현을 시작해 보겠습니다

 

해당 포스팅의 글 역시 기존 OpenCvSharp 포스팅 자료와 이어서 진행되오니

 

이해가 안가거나 중간 생략된 부분은 이전 포스팅을 참조하시기 바랍니다

 

https://codingman.tistory.com/49

 

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

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

codingman.tistory.com

 

그럼 프로그램 동작을 위한 디자인 부분부터 설명하겠습니다

 

[디자인]

- 메뉴에 머쉰런닝 탭에 PCA 버튼을 만들고 학습과 검출의 세부 버튼을 생성합니다

 

- 학습과 검출 세부 버튼에 클릭시 동작 할 수 있도록 이벤트를 활성화 시킵니다

 

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

 

* 학습

        private void 학습ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            using (PCA pca = new PCA())
            using (IplImage temp = pca.LearnPCA())
            {
                if (temp == null)
                {
                    MessageBox.Show("데이타 파일 오류");
                    return;
                }
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;
        }

 

*검출

        private void 검출ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (PCA pca = new PCA())
            {
                String[] temp = pca.recognize();
                if (temp == null) MessageBox.Show("오류발생 확인요망");
                for (int i = 0; i < temp.Length; i++)
                    listBox1.Items.Add(temp[i]);

            }
        }

 

- PCA 기능 동작을 위한 클래스 파일 생성합니다

 

- 생성된 클래스에 다음과 같이 소스코드를 작성 합니다

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

namespace OpenCV_V1
{
    class PCA : IDisposable
    {
        #region 초기값
        int nTrainFaces = 0;
        int nEigens = 0;

        IplImage result;
        IplImage[] faceImgArr;
        IplImage[] eigenVectArr;
        IplImage pAvgTrainImg;
        float[,] projectedTrainFaceMat;
        float[] eigenValMat;
        CvMat personNumTruthMat;

        public void Dispose()
        {
            if (result != null) Cv.ReleaseImage(result);
            if (!pAvgTrainImg.IsDisposed) pAvgTrainImg.Dispose();
            if (!faceImgArr[0].IsDisposed)
            {
                for (int i = 0; i < nTrainFaces; i++)
                {
                    faceImgArr[i].Dispose();
                }
            }
            if (!eigenVectArr[0].IsDisposed)
            {
                for (int i = 0; i < nEigens; i++)
                    eigenVectArr[i].Dispose();
            }
            if (!personNumTruthMat.IsDisposed) Cv.ReleaseMat(personNumTruthMat);
        }
        #endregion

        #region PCA 학습

        public unsafe IplImage LearnPCA()
        {
            //학습할 이미지 사진 파일명을 나열한 텍스파일 읽기
            nTrainFaces = loadFaceImgArray("train.txt");
            if (nTrainFaces < 2)
            {
                //MessageBox.Show("데이타 파일이 잘못 되었슴");
                return null;
            }

            doPCA();

            projectedTrainFaceMat = new float[nTrainFaces, nEigens];
            float[] tempProject = new float[nEigens];

            for (int i = 0; i < nTrainFaces; i++)
            {
                Cv.EigenDecomposite(faceImgArr[i], eigenVectArr, pAvgTrainImg, tempProject);//projectedTrainFaceMat[i]);
                projectedTrainFaceMat[i, 0] = tempProject[0];
                projectedTrainFaceMat[i, 1] = tempProject[1];
            }


            storeTraingData();
            return result;
        }

        private int loadFaceImgArray(String file)
        {
            //텍스트 파일에 나열되어진 파일명대로 이미지 읽어서 메모리에 저장하기   
            int i = 0;
            string[] lines = File.ReadAllLines(file); //학습할 파일명 획득
            faceImgArr = new IplImage[lines.Length]; //학습할 얼굴 갯수만큼 메모리 확보

            foreach (string line in lines) //텍스트 파일에서 읽은 파일명으로
            {
                faceImgArr[i] = new IplImage(lines[i], LoadMode.GrayScale); //사진이미지 읽어 오기
                i++;
            }
            return lines.Length;

        }

        private unsafe void doPCA()
        {
            CvTermCriteria calcLimit;
            CvSize faceImgSize;
            nEigens = nTrainFaces - 1;

            faceImgSize.Width = faceImgArr[0].Width;
            faceImgSize.Height = faceImgArr[0].Height;

            eigenVectArr = new IplImage[nEigens];

            for (int i = 0; i < nEigens; i++)
                eigenVectArr[i] = new IplImage(faceImgSize, BitDepth.F32, 1);

            eigenValMat = new float[nEigens];
            pAvgTrainImg = new IplImage(faceImgSize, BitDepth.F32, 1);
            calcLimit = new CvTermCriteria(CriteriaType.Iteration, nEigens, 1);
            Cv.CalcEigenObjects(faceImgArr, eigenVectArr, 0, calcLimit, pAvgTrainImg, eigenValMat);

        }

        //학습된 데이타 저장하기
        private void storeTraingData()
        {
            int[] faceID = { 1, 2, 4, 5 };//사실은 텍스트 파일에 같이 써야 하지만 분리하기 귀찮아서
            personNumTruthMat = new CvMat(1, nTrainFaces, MatrixType.S32C1, faceID);

            using (CvFileStorage fs = new CvFileStorage("facedata.xml", null, FileStorageMode.Write))
            using (CvMat eigen = new CvMat(1, nEigens, MatrixType.F32C1, eigenValMat))
            using (CvMat projected = new CvMat(nTrainFaces, nEigens, MatrixType.F32C1, projectedTrainFaceMat))
            {
                fs.WriteInt("nEigens", nEigens);
                fs.WriteInt("nTrainFaces", nTrainFaces);
                fs.Write("trainPersonNumMat", personNumTruthMat);
                fs.Write("eigenValMat", eigen);
                fs.Write("projectedTrainFaceMat", projected);
                fs.Write("avgTrainImg", pAvgTrainImg);

                for (int i = 0; i < nEigens; i++)
                {
                    String varName = String.Format("eigenVect_{0}", i);
                    fs.Write(varName, eigenVectArr[i]);
                }
                result = new IplImage(pAvgTrainImg.Size, BitDepth.U8, 1);
                //Currentley, bitmap converter can read not only BitDeth.U8 but also 32F
                Cv.CvtScale(pAvgTrainImg, result);
            }
        }
        #endregion

        #region PCA 인식

        public unsafe String[] recognize()
        {
            String[] str;

            int nTestFaces = 0; //비교할 이미지 숫자
            CvMat trainPersonNumMat; //학습으로 저장된
            float[] projectedTestFace;

            nTestFaces = loadFaceImgArray("test.txt"); //얼굴갯수 리턴
            projectedTestFace = new float[nEigens];

            if (!loadTranningData(out trainPersonNumMat)) return null;

            projectedTrainFaceMat = new float[trainPersonNumMat.Rows, trainPersonNumMat.Cols];//배열확보
            float[] tempProject = new float[nEigens];

            for (int i = 0; i < trainPersonNumMat.Rows; i++)
                for (int j = 0; j < trainPersonNumMat.Cols; j++)
                    projectedTrainFaceMat[i, j] = (float)Cv.mGet(trainPersonNumMat, i, j); //저장된 값 이동

            str = new String[nTestFaces]; //비교할 파일 갯수 만큼

            for (int i = 0; i < nTestFaces; i++)
            {
                int iNearest, nearest, truth;

                Cv.EigenDecomposite(faceImgArr[i], eigenVectArr, pAvgTrainImg, tempProject);

                iNearest = findNearestNeighbor(tempProject); //근접도
                truth = (int)Cv.mGet(personNumTruthMat, 0, i); //실제 명기된 ID
                nearest = (int)Cv.mGet(personNumTruthMat, 0, iNearest);

                str[i] = String.Format("nearest ID ={0}, Real ID = {1}", nearest, truth);

            }
            return str;


        }

        private int findNearestNeighbor(float[] projecTestFace)
        {
            double leastDistSq = 1e12;// DBL_MAX;
            int iTrain, iNearest = 0;

            for (iTrain = 0; iTrain < nTrainFaces; iTrain++) //비교할 얼굴 갯수
            {
                double distSq = 0;

                for (int i = 0; i < nEigens; i++)
                {
                    float d_i = projecTestFace[i] - projectedTrainFaceMat[iTrain, i];//학습 파일에서 읽은 값과
                    //distSq += d_i*d_i / eigenValMat->data.fl;  // 마할노비스 거리
                    distSq += d_i * d_i; // 유클리디안 거리
                }

                if (distSq < leastDistSq) //더 근접한 값이 있는지 찾음
                {
                    leastDistSq = distSq;
                    iNearest = iTrain;     //몇번째 얼굴인지
                }
            }
            return iNearest;
        }

        //저장된 학습 데이타 읽어 오기
        private bool loadTranningData(out CvMat pTrainPersonNumMat)
        {
            CvFileNode param;

            using (CvFileStorage fs = new CvFileStorage("facedata.xml", null, FileStorageMode.Read))
            {
                pTrainPersonNumMat = null;
                if (fs == null) return false;

                nEigens = fs.ReadIntByName(null, "nEigens");//고유치
                nTrainFaces = fs.ReadIntByName(null, "nTrainFaces"); //학습 갯수
                param = Cv.GetFileNodeByName(fs, null, "trainPersonNumMat");
                personNumTruthMat = fs.Read<CvMat>(param); //얼굴ID

                param = Cv.GetFileNodeByName(fs, null, "projectedTrainFaceMat");//학습된 값
                pTrainPersonNumMat = fs.Read<CvMat>(param);

                param = Cv.GetFileNodeByName(fs, null, "avgTrainImg"); //학습한 평균 이미지
                pAvgTrainImg = fs.Read<IplImage>(param);
                eigenVectArr = new IplImage[nEigens];
                for (int i = 0; i < nEigens; i++)
                {
                    String varName = String.Format("eigenVect_{0}", i);
                    param = Cv.GetFileNodeByName(fs, null, varName);
                    eigenVectArr[i] = fs.Read<IplImage>(param);
                }

            }
            int[] faceID = { 1, 2, 4, 5, 1, 2, 4, 5, 1, 2, 4, 5, 1, 2, 4, 5, 1, 2, 4, 5, 1, 2, 4, 5 };//사실은 텍스트 파일에 같이 써야 하지만 분리하기 귀찮아서
            personNumTruthMat = new CvMat(1, nTrainFaces, MatrixType.S32C1, faceID);//ID 배정

            return true;
        }
        #endregion
    }
}

 

- 해당 클래스가 정상 동작을 하기 위한 기초 첨부파일을 다운 받습니다

S1245_XML.zip
0.39MB

 

- 첨부파일의 내용을 Debug 폴더에 붙여 넣기 합니다

 

*첨부파일 내용

1) s1,s2,s4,s5 비교 그룹 이미지 (형식 : bpm)

   (샘플 얼굴 이미지 사진 입니다)

 

2) test.txt

   : 그룹에 포함되어 있는 파일 정보

 

3) train.txt

   : 그룹에 대표 이미지 지정

 

3) facedata.xml

   : 학습 정보 기록을 위한 xml

 

- 실행 한뒤 각 그룹 이미지 폴더에서 1.bpm을 불러와 검출을 시도합니다

 

[결과 창]

 

 

- 저는 샘플 사진으로 트와이스 맴버를 bpm으로 전환하여 비교 하여 다른 얼굴들과 어느정도 분석이 가능한지

  테스트를 해봤습니다(좋아하니깐!)

 

- 쯔위는 s5 그룹에 대표입니다

 

- 좌측 listBox1의 결과를 분석하면 해당 폴더의 그룹별 매칭 상태가 나타나는데 90%로 정도 쯔위를 판별해

  내는것을 볼수 있습니다

 

- 해당 자료를 구현하여 다른 샘플을 통해 다른 각도로 수정하여 응용해 보시기 바랍니다

 

반응형
반응형

안녕하세요

 

이번 포스팅에서는 OpenCvSharp 기능을 통해서 이미지속의 피부색을 검출하고 검출된 영역에

 

윤곽선을 표기하고 표시된 윤곽선 내부에 포함된 오목 부분을 추가 검출하여 손가락의 구분을 

 

나누어 보도록 하겠습니다

 

이번 포스팅도 OpenCvSharp 기능 구현 포스팅으로 처음 포스팅 내용과 이어지는 부분이

 

존재합니다

 

이해가 잘 되지 않으시다면 앞전 포스팅을 읽어보시고 보신다면 이해가 좀 더 빠를거 같아서

 

아래 OpenCvSharp의 처음 포스팅을 링크해 드리겠습니다

https://codingman.tistory.com/49

 

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

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

codingman.tistory.com

[디자인]

- 메뉴버튼을 생성합니다

 

-생성한 메뉴에 클릭시 발생할 이벤트를 생성합니다

 

-생성된 클릭 이벤트 부분에 아래와 같이 코딩해줍니다

 

[Source Code]

        private void 피부색검출ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ConvextyDefect Cx = new ConvextyDefect();
            Cx.ConvextyDefectb();
        }

 

- 그다음 피부색 검출을 위한 기능 구현을 위해 클래스 파일을 생성합니다

   (클래스명칭은 ConvextyDefect.cs로 생성하였습니다.)

 

[Source Code]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;
using OpenCvSharp.Blob;
using OpenCvSharp.CPlusPlus;
using OpenCvSharp.UserInterface;

namespace OpenCV_V1
{
    class ConvextyDefect
    {
        public void ConvextyDefectb()
        {
            using (IplImage imgSrc = new IplImage("hand.jpg", LoadMode.Color))
            using (IplImage imgHSV = new IplImage(imgSrc.Size, BitDepth.U8, 3))
            using (IplImage imgH = new IplImage(imgSrc.Size, BitDepth.U8, 1))
            using (IplImage imgS = new IplImage(imgSrc.Size, BitDepth.U8, 1))
            using (IplImage imgV = new IplImage(imgSrc.Size, BitDepth.U8, 1))
            using (IplImage imgBackProjection = new IplImage(imgSrc.Size, BitDepth.U8, 1))
            using (IplImage imgFlesh = new IplImage(imgSrc.Size, BitDepth.U8, 1))
            using (IplImage imgHull = new IplImage(imgSrc.Size, BitDepth.U8, 1))
            using (IplImage imgDefect = new IplImage(imgSrc.Size, BitDepth.U8, 3))
            using (IplImage imgContour = new IplImage(imgSrc.Size, BitDepth.U8, 3))
            using (CvMemStorage storage = new CvMemStorage())
            {
                //RGB -> HSV
                Cv.CvtColor(imgSrc, imgHSV, ColorConversion.BgrToHsv);
                Cv.CvtPixToPlane(imgHSV, imgH, imgS, imgV, null);
                IplImage[] hsvPlanes = { imgH, imgS, imgV };

                //피부색 영역을 구한다
                RetrieveFleshRegion(imgSrc, hsvPlanes, imgBackProjection);
                
                //최대의 면적의 영역을 남긴다
                FilterByMaximalBolb(imgBackProjection, imgFlesh);
                Interpolate(imgFlesh);

                //윤곽을 구한다
                CvSeq<CvPoint> contours = FindContours(imgFlesh, storage);
                if(contours != null)
                {
                    Cv.DrawContours(imgContour, contours, CvColor.Red, CvColor.Green, 0, 3, LineType.AntiAlias);

                    //요철을 구한다
                    int[] hull;
                    Cv.ConvexHull2(contours, out hull, ConvexHullOrientation.Clockwise);
                    Cv.Copy(imgFlesh, imgHull);

                    DrawConvexHull(contours, hull, imgHull);

                    //오목한 상태 결손을 구한다
                    Cv.Copy(imgContour, imgDefect);
                    CvSeq<CvConvexityDefect> defect = Cv.ConvexityDefects(contours, hull);
                    DrawDefects(imgDefect, defect);

                }
                using (new CvWindow("src", imgSrc))
                using (new CvWindow("back projection", imgBackProjection))
                using (new CvWindow("hull", imgHull))
                using (new CvWindow("defect", imgDefect))
                {
                    Cv.WaitKey();
                }
            }
        }

        ///<summary>
        ///백 프로젝션에 의해 피부색 영역을 구한다
        ///</summary>
        ///<param name="imgSrc"></param>
        ///<param name="hsvPlanes"></param>
        ///<param name="imgDst"></param>
        private void RetrieveFleshRegion(IplImage imgSrc, IplImage[] hsvPlanes, IplImage imgDst)
        {
            int[] histSize = new int[] { 30, 32 };
            float[] hRanges = { 0.0f, 20f };
            float[] sRanges = { 50f, 255f };
            float[][] ranges = { hRanges, sRanges };
            imgDst.Zero();
            using (CvHistogram hist = new CvHistogram(histSize, HistogramFormat.Array, ranges, true))
            {
                hist.Calc(hsvPlanes, false, null);
                float minValue, maxValue;
                hist.GetMinMaxValue(out minValue, out maxValue);
                hist.Normalize(imgSrc.Width * imgSrc.Height * 255 / maxValue);
                Cv.CalcBackProject(hsvPlanes, imgDst, hist);
            }
        }

        ///<summary>
        ///라벨링에 의해 최대 면적의 영역을 남긴다
        ///</summary>
        ///<param name="imgSrc"></param>
        ///<param name="imgDst"></param>
        private void FilterByMaximalBolb(IplImage imgSrc, IplImage imgDst)
        {
            CvBlobs blobs = new CvBlobs();

            imgDst.Zero();
            blobs.Label(imgSrc);
            CvBlob max = blobs.GreaterBlob();
            if (max == null)
            {
                return;
            }
            blobs.FilterByArea(max.Area, max.Area);
            blobs.FilterLabels(imgDst);
        }

        ///<summary>
        ///결손 영역을 보완한다
        ///</summary>
        ///<param name="img"></param>
        private void Interpolate(IplImage img)
        {
            Cv.Dilate(img, img, null, 2);
            Cv.Erode(img, img, null, 2);
        }

        ///<summary>
        ///윤곽을 얻는다
        ///</summary>
        ///<param name="img"></param>
        ///<param name="storage"></param>
        ///<returns></returns>
        private CvSeq<CvPoint> FindContours(IplImage img, CvMemStorage storage)
        {
            //윤곽 추출
            CvSeq<CvPoint> contours;
            using (IplImage imgClone = img.Clone())
            {
                Cv.FindContours(imgClone, storage, out contours);
                if(contours == null)
                {
                    return null;
                }
                contours = Cv.ApproxPoly(contours, CvContour.SizeOf, storage, ApproxPolyMethod.DP, 3, true);
            }

            //제일 긴 것 같은 윤곽만을 얻는다
            CvSeq<CvPoint> max = contours;
            for(CvSeq<CvPoint> c = contours; c != null; c=c.HNext)
            {
                if(max.Total < c.Total)
                {
                    max = c;
                }
            }
            return max;
        }

        ///<summary>
        ///ConvexHull 그리기
        ///</summary>
        ///<param name="contours"></param>
        ///<param name="hull"></param>
        ///<param name="img"></param>
        private void DrawConvexHull(CvSeq<CvPoint> contours, int[] hull, IplImage img)
        {
            CvPoint pt0 = contours[hull.Last()].Value;

            foreach(int idx in hull)
            {
                CvPoint pt = contours[idx].Value;
                Cv.Line(img, pt0, pt, new CvColor(255, 255, 255));
                pt0 = pt;
            }

        }

        ///<summary>
        ///ConvexityDefects 그리기
        ///</summary>
        ///<param name="img"></param>
        ///<param name="defect"></param>
        private void DrawDefects(IplImage img, CvSeq<CvConvexityDefect> defect)
        {
            int count = 0;
            foreach(CvConvexityDefect item in defect)
            {
                CvPoint p1 = item.Start, p2 = item.End;
                double dist = Getdistance(p1, p2);
                CvPoint2D64f mid = GetMidpoint(p1, p2);
                img.DrawLine(p1, p2, CvColor.White, 3);
                img.DrawCircle(item.DepthPoint, 10, CvColor.Green, -1);
                img.DrawLine(mid, item.DepthPoint, CvColor.White, 1);
                Console.WriteLine("No:{0} Depth:{1} Dist:{2}", count, item.Depth, dist);
                count++;
            }
        }

        ///<summary>
        ///2점간의 거리를 얻는다
        ///</summary>
        ///<param name="p1"></param>
        ///<param name="p2"></param>
        ///<returns></returns>
        private double Getdistance(CvPoint p1, CvPoint p2)
        {
            return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
        }

        ///<summary>
        ///2점의 중점을 얻는다
        ///</summary>
        ///<param name="p1"></param>
        ///<param name="p2"></param>
        ///<returns></returns>
        private CvPoint2D64f GetMidpoint(CvPoint p1, CvPoint p2)
        {
            return new CvPoint2D64f
            {
                X = (p1.X + p2.X) / 2.0,
                Y = (p1.Y + p2.Y) / 2.0
            };
        }
    }
}

 

- "hand.jgp"파일은 해당 프로젝트의 Debug 폴더에 넣으시면 되고 예제 파일은 제가 사용한 파일을 업로드

 

하겠습니다

 

hand.JPG
0.03MB

 

- 이렇게 이미지 파일을 넣은 뒤 빌드하여 실행하시면 다음과 같은 결과가 나타나게 됩니다

 

[결과 창]

*원본이미지

* Back projection

 

*hull

 

*defect

반응형
반응형

안녕하세요

 

C# 컨텐츠로 블로그를 운영중인 코딩 연습생입니다

 

이번 포스팅에서는 C#으로 MSSQL를 접속하고 쿼리문을 전송시켜 연동시키기까지 한번 해보도록 하겠습니다

 

일반적인 방법으로는 

1) 접속정보 생성

2) SqlConnection 생성

3) SqlDataAdapter 생성

4) SqlCommand 실행

5) DataSet 실행

6) DataTable 데이터 받기

 

이런 순서로 직접 날코딩하여 사용을 했었습니다

 

그런데 프로젝트에서 DB 통신을 자주해야 하는경우 매우 귀찮아지게 됩니다

 

그래서 쉽게 MSSQL과 통신하고 내가 원하는 방식으로 FeedBack 받을수 있는 클래스 생성도 같이 설명해보

 

도록 하겠습니다

 

첫번째로 일반 방식입니다

string source = string.Empty;
string SYS_TIME = string.Empty;

//콜렉션 생성
DataRowCollection Rs2 = null;
//접속정보 생성
source = @"User Id=계정ID;Password=패스워드;Server=tjqjIP;Initial Catalog=DB명";

//컨넥션 생성
SqlConnection Con = new SqlConnection(source);
Con.Open();
SqlDataAdapter adapter = new SqlDataAdapter();
string query = "쿼리";
adapter.SelectCommand = new SqlCommand(query, Con);
DataSet ds = new DataSet();
adapter.Fill(ds);
DataTable table = ds.Tables[0];
Rs2 = table.Rows;

if (Rs2 != null && Rs2.Count > 0)
{
	for (int i = 0; i < Rs2.Count; i++)
	{
		//쿼리에서 FeedBack 받은 값 사용
        SYS_TIME = Rs2[0]["시간"].ToString();
	}
}
Con.Close();

 

단순한 SELECT문 하나 사용하더라도 참 많은 구문을 작성해야 합니다

 

두번째 방법으로는 클래스로 DB 명령를 미리 생성해놓고 호출하여 사용하는 방식으로 구현해 볼께요

1) DB에서 사용될 명령를 미리 생성합니다

   - Database.cs라는 구성 요소 클래스 파일 생성

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

namespace db_conn
{
    public partial class Database : Component
    {
        public Database()
        {
            InitializeComponent();
        }

        public Database(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
        }

        private db_conn.BaseDB.DBTypeEnum m_DbType = BaseDB.DBTypeEnum.JDE;

        public db_conn.BaseDB.DBTypeEnum DbType
        {
            get { return m_DbType; }
            set { m_DbType = value; }
        }

        /// <summary>
        /// SELECT처럼 결과가 있는 쿼리를 실행한다
        /// </summary>
        /// <param name="query">쿼리</param>
        /// <returns>데이터테이블</returns>
        public DataTable ExcuteQuery(string query)
        {
            return ExcuteQuery(m_DbType.ToString(), query);
        }
        /// <summary>
        /// SELECT처럼 결과가 있는 쿼리를 실행한다
        /// </summary>
        /// <param name="dbName">DB명</param>
        /// <param name="query">쿼리</param>
        /// <returns>데이터테이블</returns>
        public DataTable ExcuteQuery(string dbName, string query)
        {
            db_conn.BaseDB db = BaseDB.GetDB(dbName.ToUpper());
            return db.ExcuteQuery(query);
        }
        /// <summary>
        /// insert, update처럼 조작하는 쿼리를 실행한다.
        /// </summary>
        /// <param name="query">쿼리</param>
        /// <returns>결과</returns>
        public int ExcuteNonQuery(string query)
        {
            return ExcuteNonQuery(m_DbType.ToString(), query);
        }
        // <summary>
        /// insert, update처럼 조작하는 쿼리를 실행한다.
        /// </summary>
        /// <param name="dbName">DB명</param>
        /// <param name="query">쿼리</param>
        /// <returns>결과</returns>
        public int ExcuteNonQuery(string dbName, string query)
        {
            db_conn.BaseDB db = BaseDB.GetDB(dbName.ToUpper());
            return db.ExcuteNonQuery(query);
        }
        /// <summary>
        /// 대량의 데이터를 인서트한다.
        /// </summary>
        /// <param name="toTbName">인서트할 테이블</param>
        /// <param name="dt">데이터테이블</param>
        /// <returns>오류메세지</returns>
        public string BulkInsert(string toTbName, System.Data.DataTable dt)
        {
            return BulkInsert(m_DbType.ToString(), toTbName, dt);
        }
        /// <summary>
        /// 대량의 데이터를 인서트한다.
        /// </summary>
        /// <param name="dbName">DB명</param>
        /// <param name="toTbName">인서트할 테이블</param>
        /// <param name="dt">데이터테이블</param>
        /// <returns>오류메세지</returns>
        public string BulkInsert(string dbName, string toTbName, System.Data.DataTable dt)
        {
            db_conn.BaseDB db = BaseDB.GetDB(dbName.ToUpper());
            return db.BulkInsert(toTbName, dt);
        }

        /// <summary>
        /// 1:1매칭되는 테이블을 넘겨 Dictionary로 받는다.
        /// </summary>
        /// <param name="dbName">DB명</param>
        /// <param name="query">쿼리(KEY_COL,VAL_COL이 반드시 있어야한다)</param>
        /// <returns>결과</returns>
        public Dictionary<string, string> GetDic1To1(string dbName, string query)
        {
            Dictionary<string, string> ret = new Dictionary<string, string>();
            DataTable dt = ExcuteQuery(dbName, query);
            string key = "";
            string val = "";
            for (int row = 0; row < dt.Rows.Count; row++)
            {
                key = dt.Rows[row]["KEY_COL"].ToString();
                val = dt.Rows[row]["VAL_COL"].ToString();
                if (!ret.ContainsKey(key))
                {
                    ret.Add(key, val);
                }
            }
            return ret;
        }
        /// <summary>
        /// 테이블을 넘겨 Dictionary(row)
        /// </summary>
        /// <param name="dbName">DB명</param>
        /// <param name="query">쿼리(KEY_COL은 반드시 있어야한다)</param>
        /// <returns>결과</returns>
        public Dictionary<string, DataRow> GetDicRow(string dbName, string query)
        {
            Dictionary<string, DataRow> ret = new Dictionary<string, DataRow>();
            DataTable dt = ExcuteQuery(dbName, query);
            string key = "";
            for (int row = 0; row < dt.Rows.Count; row++)
            {
                key = dt.Rows[row]["KEY_COL"].ToString();
                if (!ret.ContainsKey(key))
                {
                    ret.Add(key, dt.Rows[row]);
                }
            }
            return ret;

        }

        /// <summary>
        /// 데이터테이블을 딕셔너리에 넣는다.
        /// </summary>
        /// <param name="keyCols">키값을 가지는 컬럼들(:로 연결한다)</param>
        /// <param name="dt">넘길 테이블</param>
        /// <returns>결과</returns>
        public Dictionary<string, DataRow> GetDicRow(string keyCols, DataTable dt)
        {
            Dictionary<string, DataRow> ret = new Dictionary<string, DataRow>();

            string key = "";
            string[] spKeys = keyCols.Split(':');
            for (int row = 0; row < dt.Rows.Count; row++)
            {
                key = "";
                for (int i = 0; i < spKeys.Length; i++)
                {
                    key += dt.Rows[row][spKeys[i]].ToString();
                }
                if (!string.IsNullOrEmpty(key) && !ret.ContainsKey(key))
                {
                    ret.Add(key, dt.Rows[row]);
                }
            }
            return ret;
        }

        /// <summary>
        /// 데이터테이블을 딕셔너리에 넣는다.
        /// </summary>
        /// <param name="keyCols">키값을 가지는 컬럼들(:로 연결한다)</param>
        /// <param name="sumCols">SUM할 컬럼들(:로 연결한다)</param>
        /// <param name="dt">넘길 테이블</param>
        /// <returns>결과</returns>
        public Dictionary<string, DataRow> GetDicRow(string keyCols, string sumCols, DataTable dt)
        {
            Dictionary<string, DataRow> ret = new Dictionary<string, DataRow>();

            string key = "";
            string[] spKeys = keyCols.Split(':');
            string[] spSums = sumCols.Split(':');
            for (int row = 0; row < dt.Rows.Count; row++)
            {
                key = "";
                for (int i = 0; i < spKeys.Length; i++)
                {
                    key += dt.Rows[row][spKeys[i]].ToString();
                }

                if (!ret.ContainsKey(key))
                {   //INSERT
                    ret.Add(key, dt.Rows[row]);
                }
                else
                {   //UPDATE
                    for (int i = 0; i < spSums.Length; i++)
                    {
                        ret[key][spSums[i]] = Convert.ToDouble(ret[key][spSums[i]]) + Convert.ToDouble(dt.Rows[row][spSums[i]]);
                    }
                }
            }
            return ret;
        }

        /// <summary>
        /// 딕셔너리를 DataTable로 변환
        /// </summary>
        /// <param name="dic">딕셔너리</param>
        /// <returns>테이블</returns>
        public DataTable ConvertDicToDT(Dictionary<string, DataRow> dic)
        {
            DataTable dt = new DataTable();
            int cnt = 0;
            foreach (KeyValuePair<string, DataRow> pair in dic)
            {
                if (cnt == 0)
                {
                    dt = pair.Value.Table.Clone();
                }

                DataRow dr = dt.NewRow();
                for (int col = 0; col < pair.Value.ItemArray.Length; col++)
                {
                    dr[col] = pair.Value[col];
                }
                dt.Rows.Add(dr);

                cnt++;
            }

            return dt;
        }

    }
}

 

2) 접속 DB에 대한 속성 클래스 생성

   - BaseDB 클래스 파일 생성

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Reflection;
using System.Data.Common;

namespace db_conn
{
    
    public abstract class BaseDB 
    {
        #region 열거형
        /// <summary>
        /// 매출타입(OES/OEM)
        /// </summary>
        public enum DBTypeEnum
        {
            TEST            
        }
        #endregion

        private DBTypeEnum m_DBType = DBTypeEnum.TEST;

        public BaseDB(DBTypeEnum dbType)
        {
            m_DBType = dbType;
            
        }

        /// <summary>
        /// 쿼리를 실행한다(결과 있을때)
        /// </summary>
        /// <param name="query">쿼리</param>
        /// <returns>실행결과</returns>
        public abstract DataTable ExcuteQuery(string query);

        /// <summary>
        /// 쿼리를 실행한다(결과 없을때)
        /// </summary>
        /// <param name="query">쿼리</param>
        /// <returns>적용행수</returns>
        public abstract int ExcuteNonQuery(string query);


        /// <summary>
        /// 대량의 데이터를 Insert한다
        /// </summary>
        /// <param name="toTbName">저장할테이블</param>
        /// <param name="dt">데이터</param>
        /// <returns>에러메세지</returns>
        public abstract string BulkInsert(string toTbName, DataTable dt);

        /// <summary>
        /// DB연결자생성
        /// </summary>
        /// <returns>DB연결자</returns>
        protected abstract DbConnection DBConnection();

        

        /// <summary>
        /// SQL파일을 실행한다.
        /// </summary>
        /// <param name="path">SQL파일</param>
        /// <param name="args">인자(:)으로 구분</param>
        /// <returns>결과</returns>
        public DataTable ExcuteFileQuery(string path, string args)
        {
            string query = System.IO.File.ReadAllText(path);
            query = query.Replace("\r\n", " "); //강제개행
            query = query.Replace("\t", " "); //탭키
            query = query.Replace(";", " "); //탭키
            string[] spArgs = args.Split(':');
            for (int i = 0; i < spArgs.Length; i++)
            {
                query = query.Replace("{" + i.ToString() + "}", spArgs[i]);
            }
            return this.ExcuteQuery(query);
        }

        
        /// <summary>
        /// 줄리안데이트
        /// </summary>
        /// <param name="yyyymmdd">년월일</param>
        /// <returns>줄리안</returns>
        public int GetJulianDate(string yyyymmdd)
        {
            int yyyy = Convert.ToInt32(yyyymmdd.Substring(0, 4));
            int mm = Convert.ToInt32(yyyymmdd.Substring(4, 2));
            int dd = Convert.ToInt32(yyyymmdd.Substring(6, 2));
            DateTime lDate = new DateTime(yyyy, mm, dd);
            DateTime rDate = new DateTime(yyyy, 1, 1);

            string date1;
            string date2;
            date1 = "1" + yyyymmdd.Substring(2, 2);
            TimeSpan span = lDate.Subtract(rDate);

            date2 = Convert.ToString(Convert.ToUInt32(span.Days) + 1).PadLeft(3, '0');

            return Convert.ToInt32(date1 + date2);
        }

        public static BaseDB GetDB(string dbType)
        {
            BaseDB db = null;
            switch (dbType)
            {
                case "TEST":
                    db = new TEST();
                    break;
            }
            return db;
        }
    }
}

 

3) DB타입에 따른 세부 명령어 지정

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Data.Common;

namespace db_conn
{
    public class MssqlDB:BaseDB
    {
        public MssqlDB(string ip, string uid, string pwd, string db)
            : base(DBTypeEnum.MSSQL)
        {
            m_DB_IP = ip;
            m_DB_ID = uid;
            m_DB_PWD = pwd;
            m_DB_Name = db;
        }

        #region 멤버필드

        private string m_DB_IP = "";
        private string m_DB_ID = "";
        private string m_DB_PWD = "";
        private string m_DB_Name = "";

        #endregion

        #region 상수        
        private const string CN_DB_TIME = "600";    //300초까지 타임아웃한다.
        #endregion

        #region 공개메소드

        /// <summary>
        /// 대량의 DataTable을 인서트한다
        /// </summary>        
        /// <param name="toTbName">삽입할 테이블명</param>
        /// <param name="dt">데이터테이블</param>
        public override string BulkInsert(string toTbName, DataTable dt)
        {
            string ret = "";
            try
            {
                SqlBulkCopy bulk = new SqlBulkCopy(DBConnection().ConnectionString);
                bulk.DestinationTableName = toTbName;
                bulk.WriteToServer(dt);
                bulk.Close();
            }
            catch (Exception exLog)
            {
                ret = exLog.Message;
                throw new Exception(exLog.Message);

            }
            return ret;
        }

        /// <summary>
        /// 결과가 있는 쿼리를 실행
        /// </summary>
        /// <param name="query">쿼리</param>
        /// <returns>결과</returns>
        public override DataTable ExcuteQuery(string query)
        {
            DataTable dt = new DataTable();
            try
            {
                SqlDataAdapter adpt = new SqlDataAdapter(query, (SqlConnection)DBConnection());
                adpt.SelectCommand.CommandTimeout = Convert.ToInt32(CN_DB_TIME);
                adpt.Fill(dt);
            }
            catch (Exception eLog)
            {
                throw eLog;
            }
            return dt;
        }

        /// <summary>
        /// 결과가 없는 쿼리를 실행
        /// </summary>
        /// <param name="query">쿼리</param>
        /// <returns>영향받은 Row수</returns>
        public override int ExcuteNonQuery(string query)
        {
            int ret = 0;
            try
            {
                SqlConnection connect = (SqlConnection)DBConnection();
                connect.Open();
                SqlTransaction tran = connect.BeginTransaction();

                try
                {

                    SqlCommand com = new SqlCommand(query, connect, tran);
                    ret = com.ExecuteNonQuery();

                    tran.Commit();
                    connect.Close();
                }
                catch (Exception ineLog)
                {
                    tran.Rollback();
                    throw ineLog;
                }
            }
            catch (Exception eLog)
            {
                throw eLog;
            }
            return ret;
        }

        protected override DbConnection DBConnection()
        {
            string connectStr = "Server=" + m_DB_IP;
            connectStr = connectStr + ";" + "User ID = " + m_DB_ID;
            connectStr = connectStr + ";" + "Password = " + m_DB_PWD;
            connectStr = connectStr + ";" + "Initial Catalog = " + m_DB_Name;
            connectStr = connectStr + ";" + "Connection Timeout= " + CN_DB_TIME;
            SqlConnection ret = new SqlConnection(connectStr);
            return ret;
        }


        public int InsertUpdateImage(string _SQL, System.Drawing.Image _Image, string _ImageFieldName, System.Drawing.Imaging.ImageFormat _ImageFormat)
        {
            int _SqlRetVal = 0;

            try
            {
                SqlConnection con = (SqlConnection)this.DBConnection();
                con.Open();

                System.Data.SqlClient.SqlCommand _SqlCommand
                    = new System.Data.SqlClient.SqlCommand(_SQL, con);


                System.IO.MemoryStream _MemoryStream = new System.IO.MemoryStream();
                _Image.Save(_MemoryStream, _ImageFormat);


                System.Data.SqlClient.SqlParameter _SqlParameter
                    = new System.Data.SqlClient.SqlParameter("@" + _ImageFieldName, SqlDbType.Image);

                _SqlParameter.Value = _MemoryStream.ToArray();
                _SqlCommand.Parameters.Add(_SqlParameter);


                _SqlRetVal = _SqlCommand.ExecuteNonQuery();


                _SqlCommand.Dispose();
                _SqlCommand = null;
            }
            catch (Exception eLog)
            {
                throw eLog;
            }

            return _SqlRetVal;
        }

        #endregion

       
    }
}

 

이렇게 준비가 다 되시면 본문에서 DB 연결과 명령어 사용이 훨씬 간편해 집니다

 

[사용방법]

1. 사용하는 프로젝트에 빌드를 통해 생성된 구성요소클래스 파일을 참조에 넣어준다

 

2. 본문에서 db_conn을 사용하기 위한 선언문

 

3. 다음과 같은 형태로 DB 연동 사용

string SYS_TIME = string.Empty;

string Sql = " SELECT 시간";
       Sql += "  FROM A ";
TEST db = new TEST();
DataTable dt = db.ExcuteQuery(Sql);

if (dt.Rows.Count > 0)
{
	for (int i = 0; i <= dt.Rows.Count - 1; i++)
	{
		SYS_TIME = dt.Rows[i]["시간"].ToString());
	}
}

 

이렇게 하면 첫번째 방식과 동일한 결과 값을 얻을수 있습니다

 

가장 큰 차이점은 첫번째 방식은 쿼리를 종류 SELECT, INSERT, UPDATE, DELETE의 구문에 따라 방식이 조금 바뀝니다

 

그렇기 때문에 사용할때마다 코딩이 구문에 맞게 맞춰야하지요

 

하지만 두번째 방식의 경우 db의 변환 타입만 맞춰 사용하면 구문에 따른 코딩이 단순화가 된다는 점이 있습니다

 

두개 모두 구현하셔서 테스트 해보시기 바랍니다

 

감사합니다~

반응형
반응형

안녕하세요

 

벌써 OpenCv에 대해 연구한지 꽤 시간이 흘렀습니다

 

점점 난이도가 올라가면서 포스팅 자료 만드는 시간이 오래 걸리고 있습니다ㅠ

 

쉬운 기능만 구현하기에는 연습에 의미가 없고...

 

그렇다고 재미있는 기능을 따라가자니 너무 어렵고...ㅎㅎㅎ

 

그래도 존버는 승리한다는 말이 있듯이 포기하지말고 힘내서 차근차근 하나씩 도전 해보도록 하겠습니다

 

이번 업로드할 포스팅 주제는 픽셀변환입니다

 

OpenCvSharp의 함수중 CvColor을 사용하여 R,G,B 영역을 변경시켜 전체영역의 색상을 변경 시키는 것인데요

 

기존에 포스팅했던 것을 쭉 같이 봐오셨다면 그렇게 어렵게 느껴지지는 않을거 같습니다

 

이전 자료는 블로그 내에서 찾아보시거나 아래 링크를 확인하시면 찾기 쉽습니다

 

https://codingman.tistory.com/49

 

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

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

codingman.tistory.com

그러면 픽셀변환에 대해서 포스팅 시작하겠습니다

 

처음에 디자인으로 버튼 생성 부터 포스팅 할꼐요

 

[디자인]

- 필터 메뉴에서 하부메뉴로 필셀변환이라고 등록합니다

 

- 그다음 픽셀변환 버튼에 클릭시 발생할 이벤트를 생성합니다

 

- 클릭 이벤트 발생시 시행될 코드는 다음과 같습니다

        private void 픽셀변환ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (src == null) return;
            using (pix Px = new pix())
            using (IplImage temp = Px.PixelAccess(src))
            {
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;
        }

 

- 그리고 필셀변환 기능을 수행할 클래스를 생성해야 겠지요?

 

- 저는 Pix.cs라는 명칭으로 생성하였습니다

 

[pix.cs Source Code]

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

namespace OpenCV_V1
{
    class pix : IDisposable
    {
        IplImage Px;

        public IplImage PixelAccess(IplImage src)
        {

            using (IplImage img = src.Clone())
            {
                // (1) 픽셀 데이타(R,G,B)를 차례차례 취득해, 변경한다
                // 저속이지만 간단한 방법

                for (int y = 0; y < img.Height; y++)
                {
                    for (int x = 0; x < img.Width; x++)
                    {
                        CvColor c = img[y, x];
                        img[y, x] = new CvColor
                        {
                            B = (byte)Math.Round(c.B * 0.7 + 10),
                            G = (byte)Math.Round(c.G * 1.0),
                            R = (byte)Math.Round(c.R * 0.0),
                        };
                    }
                }


                /*
                // 포인터를 사용한 고속의 방법
                unsafe
                {
                    byte* ptr = (byte*) img.ImageData;    // 화소 데이터에의 포인터
                    for (int y = 0; y < img.Height; y++)
                    {
                        for (int x = 0; x < img.Width; x++)
                        {
                            int offset = (img.WidthStep * y) + (x * 3);
                            byte b = ptr[offset + 0];    // B
                            byte g = ptr[offset + 1];    // G
                            byte r = ptr[offset + 2];    // R
                            ptr[offset + 0] = (byte)Math.Round(b * 0.7 + 10);
                            ptr[offset + 1] = (byte)Math.Round(g * 1.0);
                            ptr[offset + 2] = (byte)Math.Round(r * 0.0);
                        }
                    }
                }
                //*/
                /*
                // unsafe는 아니고 IntPtr로 시도한 방법 (VB.NET 방향)
                
                    IntPtr ptr = img.ImageData;
                    for (int y = 0; y < img.Height; y++)
                    {
                        for (int x = 0; x < img.Width; x++)
                        {
                            int offset = (img.WidthStep * y) + (x * 3);
                            byte b = Marshal.ReadByte(ptr, offset + 0);    // B
                            byte g = Marshal.ReadByte(ptr, offset + 1);    // G
                            byte r = Marshal.ReadByte(ptr, offset + 2);    // R
                            Marshal.WriteByte(ptr, offset + 0, (byte)Math.Round(b * 0.7 + 10));
                            Marshal.WriteByte(ptr, offset + 1, (byte)Math.Round(g * 1.0));
                            Marshal.WriteByte(ptr, offset + 2, (byte)Math.Round(r * 0.0));
                        }
                    }
                
                //*/
                //*/

                Px = img.Clone();
                return Px;

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

 

- 이렇게 클래스 생성과 코딩까지 완료 하셨다면 빌드 하시고 실행시켜 픽셀변환을 실행해 보세요

 

[결과 창]

반응형

+ Recent posts