참고 : 왜곡 불변 차량 번호판 검출 및 인식 알고리즘 Distortion Invariant Vehicle License Plate Extraction and Recognition Algorithm

김진호 경일대학교 전자공학과 DOI : 10.5392/JKCA.2011.11.3.001
















TheDavinciCodeVol2.zip




The Davinci Code

 


 

Davinci Code 프로그램 화면

 

 

프로그램 구성

 


원본 이미지에 텍스트 파일을 추가하는 Davinci Code 프로그램 이다. 

 

 

프로그램 원리




영상의 한 픽셀을 위의 그림과 같이 구성되어 있다. 프로그램에서 입력받은 문자를 Byte 형태로 변환 후 Btye 배열에 있는 문자를 2진수로 변환한다.

 

ex) 

(서울=연합뉴스) 김동찬 기자 = 세리나 윌리엄스(3위·미국)가 빅토리아 아자렌카(1위·벨라루스)를 상대로 9연승을 기록했다. 

001010001011110010101101101111111110

 

위와 같은 문자를 이진수 형태로 변형 한다.

변환된 이진수를 각 픽셀의 R,G,B 부분에 삽입 하는 것이 이프로그램의 키 포인트 이다.

 

삽입 과정에서 R,G,B 끝자리 숫자를 조작하게되는데 조작 하는 과정에서 문자열의 이진수를 이용하여 디코딩을 할 수 있도록 삽입 하여야 한다.

 


 

프로그램에 이미지를 로딩하고 위에같은 텍스트를 입력 하도록 하면

 


 

위와 같은 화면을 확인 할 수 있다. 텍스트를 삽입하고 Make Davinci Code 버튼을 통해 인코딩을 완료하게되고, 완료되는 즉시 이미지를 저장할 수 있도록 되어 있다.

 


 

 

 

위와같이 완료된 화면을 확인 할 수 있다.

 

 

 

 

인코딩이 완료된 화면이다. 실제로 두 이미지는 눈으로 확인할 수 없을 정도로 비슷 하다. 또한 파일의 용량 또한 같다는 것을 확인 할 수 있다.




복원을 하기 위해서는 Edit 메뉴에 있는 복원 기능을 통해 복원이 가능하다.

복원을 누르게 되면 사진을 선택하는 창이 뜨게되고 코드를 입력했던 이미지를 선택하게 되면 복원이 가능하다.




복원이 완료되면 텍스트 파일을 저장할 수 있다.




 

위와 같이 복원된 파일을 확인할 수 있다. 확인 결과 문제 없이 복원이 되었다는 것을 알 수 있다.

운자의 안전을 보장하기 위해 영상 처리 기술을 기반으로 도로 정보를 검출해 운전자에 알려주고, 번튼을 직접 손으로 눌러야하는 물리적 인터페이를 대체할 차세대 인터페이스 기술을 제안한다. 제안된 기술은 카메라 한대에서 입력 받은 영상 정보를 제안된 알고리즘을 통해 앞차와의 거리, 차선, 교통 표지판을 검출하고 차량 내부를 주시하는 카메라와 운전자의 음성을 인식할 마이크를 기반으로 음성인식과 동작 인식이 결합된 인터페이스를 제공한다. 본 프로젝트에서 개발된 기술을 통해 실제 테스트를 실시해 본 결과 표지판인식, 차선검출, 앞차와의 거리 검출 등의 인식률이 약 90% 이상이었으며, 이러한 기술적 요소들은 운전자가 인지하지 못하는 상황 등에서도 적절한 정보를 운전자에게 제공해 줌으로써 교통사고 확률을 크게 낮출 수 있을 것으로 기대된다.

 

서론

 

 최근 차량의 자동주차시스템이나 운전자보조시스템과 같은 지능형 자동차에 관한 연구가 활발하게 진행되고 있다. 따라서, 차량 운전의 안정성을 높이고 사고를 예방하기 위한 운전자 보조 시스템에 대한 연구가 선행되고 있다. 차량의 운전자 보조 시스템에 관한 연구가 활발하게 진행됨에 따라 인간과 시스템 사이에 자연스럽게 정보를 교환할 수 있는 지적 인터페이스에 관한 관심이 날로 커지고 있다. 자연스럽고 지적인 인터페이스를 구축하기 위해 동작과 같은 비언어 적인 통신 수산에 대한 연구가 매우 중요하다. 본 프로젝트는 운전자의 안전을 위한 단일 카메라 기법 전방 차량검출, 차선검출, 표지판 검출 기법 및 다양한 정보 제공을 위한 인터페이스를 제공하여 생활의 질을 향상 시켜주는 통합 시스템을 기발 하였다. 이를 질제 차량에 장착하여 성능 검증을 하였다.

 

Augmented Driving System(ADS)


 

그림은 본 프로젝트에서 개발된 ADS의 전체적인 구조를 나타내고 있다. 운전자 전방의 계기판위에 HUD가 장비되고 센터페시아의 가운데 동작 인식을 위한 캠이 장비된다. HUD에 차량이탈, 앞차와의 안전거리, 표지판 인식 결과등이 표시 된다. 운전자가 자신이 조작하고자 하는 시스템의 명칭을 부르면 시스템은 작동 대기상태로 들어가며 운전자가 선택하고자 하는 메뉴를 전방 HUD 에 보여준다. 운전자가 원하는 메뉴를 다양한 동작 인식을 통해 컨트롤 한다.

 


 

 ADS에서 하드웨어 기반의 흐름도를 나타내고 있다. ADS는 원본 영상을 입력 받아 실시간 차량검출, 차선검출, 표지판 인식을 통하여 운전자 보조 시스템을 구축 하였다. HUD를 통해 계기판의 다양한 정보 중 필요한 정보 일부를 전방 표시창에 투영하여 보여준다.

 


 

Augmented Driving System은 .NetFrameWork4.0을 기반으로 하며, 영상처리 Library를 바탕으로 차선이탈 방지와, 앞차와의 거리 인식을 해주는 안전 정보 제공 엔진(Safety Engine)과 표지판을 검출하는 교통 표지판(Sign Panel) 검출 엔진으로 구성된다. 위 그림은 개발된 시스템의 소프트웨어 구조를 보여주고 있다.

 

 

차량 검출을 통한 거리 측정


 

차량과 배경 사이에서는 색상이나 조명 등이 큰 변화를 가지기 때문에 에지 정보가 두드러지게 나타난다.

차량은 가운데를 중심으로 매우 유사한 패턴을 가지기 때문에 차량에서의 유사도는 차량이 아닌 것에 비해 차량 영역에서도 높게 나타나기 때문에 차량과 비차량을 구분하여 나타낼 수 있다. 안전된 차량을 검출하기 위해 제안되 영상처리 과정은 아래와 같다.

 

수직에지 검출 -  Labeling - 차량인식 - 차간 거리 인식

흑백 영상 변환 

- 카메라로 부터 얻어온 컬러 영상을 흑백 영상으로 변환 

수직성분 검출 

- 다른 환경보다 차량에 많이 검출되는 수직 성분을 검출한다. 

영역 지정 및 Blob Labeling 

- Labeling 기법 후에 가장 큰 크기의 영역을 차량으로 인식한다. 

앞차와의 거리 검출 

- 인식된 차량의 중심점을 찾아 그 점까지의 픽셀수와 단위 거리를 이용하여 거리를 구한다. 

 

 

차선 검출을 통한 이탈 경고 시스템


 

지금까지 개발된 차선검출 기법은 칼라 성분들을 이용하는 방법, 이동 창 기법을 이용하여 입력 영상의 체크 포인트를 결정하고 차선을 검출하는 방법, 직선 성분을 찾는 대표적인 알고리즘인 허프 변환 기법 등이 있다.

안정된 차선을 검출하기 위해 본 프로젝트는 다음 과 같은 과정을 사용하였다.

 

원영상 - Gray - ROI, 이진화 - 허프변환 - 차선인식

 

흑백 영상 변환

 - 카메라로부터 얻어온 컬러 영상을 흑백영상으로 변환

영역지정 및 이진화

 - 흰색과 황색을 검출하여 이진화

Canny 연산을 통한 에지

 - 이진화한 이미지에서 외곽선을 추출하기 위해 Canny연산을 통해 윤곽선 정보를 추출한다.

Hough 변환

 - Hough 변환을 통해 일정길이 이상의 성분들을 검출하여 차선으로 인식

 

 

교통 표지판 검출


 

기계학습을 통한 학습데이터를 통하여 표지판을 검출하였다. 기계학습을 위한 이미지 데이터를 제작하였고 500x342해상도의 데이터를 학습 시켰다.

이미지 비율은 1:2와 1:3 비율을 유지해 주었다.

 

Adaboost

 - 이미지 데이터를 Adaboost 분류기 알고리즘을 통해 샘플링 과정을 통해 벡터 데이트를 만들고 생성된 벡터 데이터 파일을 통해 Haar 특징 기반 학습 과정을 통해 학습된 데이터(xml) 파일을 추출한다.

Supported Vector Machine(SVM)

 - 정규화 시킨 이미지에 SVM  매칭 기법으로 인식하여 표지판 검출을 수행한다.

 

 

동작 인식을 통한 제어기술


 

센서 장비를 착요하게 디면 인식률과 보다 많은 동작을 인식할 수 있지만 운전자에 방해가 되는 요소가 많기 때문에 일반 컬러 영상을 통해 동작 인식할 필요가 있다. 

 

원영상 - 피부색상 영역 추출 - Labeling - 중심검출 - 제스쳐 인식

 

강인한 색상 모델

 - YCbCr 칼라 공간의 히스토그램 피부색 분포 결과 Y 성분을 제외한 Cb,Cr 성분의 값이 밀집도가 크고 조도 변화에 따른 변화가 거의 없다는 결과를 얻었다. H, Cb,Cr 각 성분 값을 정규화된 R,G,B값을 이용하여 구한다.

손 후보 영역 검출

 - 수행된 영상에 가장 큰 영역을 검출하게 되면 손에 가장 정확한 영역이 추출된다.

손 중심점 추출에 의한 동작 인식

 - 손 영역의 무게 중심을 구하여 이에 움직임을 통해 제스쳐를 인식하는 방법을 사용한다. 추출된 손 영역에서 무게 주심은 화소들의 합으로 나타낼 수 있다.

개요 

현재 보금화된 감시 프로그램의 부족한 점을 보안

 - 무분변한 녹화(대용량 데이터 필요)

  얼굴인식

  움직임 감시

 - 발생 후 대처

  사용자에게 통보(클라이언트, 안드로이드 어플리케이션)

 

CCTV를 통한 감시 뿐만 아닌 반응 필요

 



 

얼굴비교는 인식된 얼굴을 얼굴 DNA정보를 통해 비교하여 등록된 얼굴인지를 검사하여 신고여부를 결정한다.

검사결과 미 등록일 경우 신고 및 관리자에게 알림

 


 

 

본 프로그램은 .Net Framework 4.0 을 기반으로 제작 되었으며 Motion Dectection Engine 과 Face Detection Engine은 OpenCV를 이용하여 제작 되었습니다.

 

그위에 FaceDNA검출 기법을 통하여 C.R.R클라이언트를 구현 하였습니다.

 

Android Application은 Android4.0.3 기반에 Ksoap2 Library 를 사용하여 구현하였고

 

이 둘은 WebService를 통하여 상호간에 통신을 가능하게 구현 하였습니다.

 

결론 및 기대 효과

- 효율적인 CCTV 관리를 가능하게 할 것이며, 가정이나 가게들의 보안을 강화 할 수 있을 것입니다.

- 인건비 전약을 가능하게 할 것입니다.

 

향후 개선 방향

- 여러 각도에서의 얼굴 인식

- 실시간 스트리밍 서비스

- 안정화

 

 

 

시연 동영상

 

클라이언트



C.R.R 움직임 감지와 얼굴 DNA 검출을 통한 CCTV 개선 프로그램  CozyProgram / 프로그래밍 

2012.05.31. 22:08  수정  삭제

복사http://blog.naver.com/smhotkdg/60163653224

통계보기 전용뷰어 보기

개요 

현재 보금화된 감시 프로그램의 부족한 점을 보안

 - 무분변한 녹화(대용량 데이터 필요)

  얼굴인식

  움직임 감시

 - 발생 후 대처

  사용자에게 통보(클라이언트, 안드로이드 어플리케이션)

 

CCTV를 통한 감시 뿐만 아닌 반응 필요

 

 

얼굴비교는 인식된 얼굴을 얼굴 DNA정보를 통해 비교하여 등록된 얼굴인지를 검사하여 신고여부를 결정한다.

검사결과 미 등록일 경우 신고 및 관리자에게 알림

 

 

 

본 프로그램은 .Net Framework 4.0 을 기반으로 제작 되었으며 Motion Dectection Engine 과 Face Detection Engine은 OpenCV를 이용하여 제작 되었습니다.

 

그위에 FaceDNA검출 기법을 통하여 C.R.R클라이언트를 구현 하였습니다.

 

Android Application은 Android4.0.3 기반에 Ksoap2 Library 를 사용하여 구현하였고

 

이 둘은 WebService를 통하여 상호간에 통신을 가능하게 구현 하였습니다.

 

결론 및 기대 효과

- 효율적인 CCTV 관리를 가능하게 할 것이며, 가정이나 가게들의 보안을 강화 할 수 있을 것입니다.

- 인건비 전약을 가능하게 할 것입니다.

 

향후 개선 방향

- 여러 각도에서의 얼굴 인식

- 실시간 스트리밍 서비스

- 안정화

 

 

 

시연 동영상

 

클라이언트

 


 

 

안드로이드




< JAVA 설치하기 >


- 오라클홈페이지 Java SE Development Kit  (JDK) 다운로드


- JDK = Java, JVM(가상머신)

  윈도우, 리눅스, 맥 등 어느 운영체제든 실행이 가능한 이유는?  JVM


1. 시스템 변수에 jdk 경로를 추가 시킵니다.



2. Path에 시스템 변수에서 추가시킨 jdk 경로를 입력해주면 끝.





이제 cmd 창에서 잘 설치가 되었는지 확인하도록 하겠습니다.

< cmd 실행방법 >


1. 윈도우R - cmd 

java -version

 javac -version


위 화면과 같이 나오면 최초 환경변수 설정은 끝났습니다~

'Programing > Java' 카테고리의 다른 글

JAVA 흐름제어문 (break문, contunue문, return문)  (0) 2018.12.12
객체지향의 특징 요약  (0) 2016.12.18
객체 지향 프로그래밍 이란?  (0) 2016.12.01

State Pattern(상태 패턴)?

상태변화를 가지는 주요 객체를 다룰 때 유용하게 적용해 볼 수 있는 패턴이다.

의도

객체의 내부 상태에 따라 스스로 행동을 변경할 수 있게 허가하는 패턴으로 이렇게 하면 개체는 마치 자신의 클래스를 바꾸는 것처럼 보인다.

 


 

서브클래스들이 상속 받을 State를 다음과 같이 만든다.

모두 가상 메서드로 이루어지고 각 가상 메서드는 에러처리만 하도록 만든다. 후손개체의 메서드가 사용되지 않고, 조상 개체의 메서드가 사용되면 자동으로 에러가 나도록 만든다.

State.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace StatePattern

{

    class State

    {

        public virtual bool Attack(Character character)

        {

            Console.WriteLine("공격 오류!");

            return false;

        }

        public virtual bool Move(Character character)

        {

            Console.WriteLine("이동 오류 !");

            return false;

        }

        public virtual bool Lucky(Character character)

        {

            Console.WriteLine("행운 오류!");

            return false;

        }

        public virtual void CountDown(Character character)

        {

        }

    }

}

 

 

싱글톤패턴 적용하여 시스템에 하나의 개체만 존재하도록 하였고, 생성자 캐릭터 개체를 입력 받도록 만들어주어, 나중에 상태개체를 변경해야 할 때 사용한다

 

Normal.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace StatePattern

{

    class Normal : State

    {

        private static Normal this_object;

        public static Normal get_object

        {

            get

            {

                if (this_object == null)

                {

                    this_object = new Normal();

                }

                return this_object;

            }

        }

        public override bool Attack(Character character)

        {

            Console.WriteLine("100% 공격력!!");

            character.Hp -= 40;

            if (character.Hp < 30)

            {

                character.chageState(Emergency.get_object);

            }

            return true;

        }

        public override bool Move(Character character)

        {

            Console.WriteLine("100% 이동!!");

            //character.chageState(Superman.get_object);

            return true;

        }

      

    }

}

 

 

Emergency.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace StatePattern

{

    class Emergency : State

    {

        Random rand = new Random();

        private static Emergency this_object;

        public static Emergency get_object

        {

            get

            {

                if (this_object == null)

                {

                    this_object = new Emergency();

                }

                return this_object;

            }

        }

        public override bool Attack(Character character)

        {

            int luck=0;

            Console.WriteLine("공격 75 %!!");

            luck = rand.Next(3);

            if (luck == 2)

            {

                character.chageState(Immortal.get_object);

                Immortal.before_state = this;

            }

            return true;

        }

        public override bool Move(Character character)

        {

            Console.WriteLine("이동 50%!!");

            return true;

        }

        public override bool Lucky(Character character)

        {           

            Console.WriteLine("행운 15!");

            return true;

        }

    }

}

 

 

 

※ 캐릭터를 담당 하게 될 Character  클래스를 보도록 하자Character Class 내부에 State 개체를 가지게 되는데, 이 개체는 수시로 각 상태를 담당하는 개체로 형 변환을 하게 된다.

 

Character.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace StatePattern

{

    class Character

    {

        int hp;

        private State state;

        public Character()

        {

            hp = 100;

            chageState(Normal.get_object);

        }

        public int Hp

        {

            get

            {

                return hp;

            }

            set

            {

                hp = value;

            }

        }

        public void chageState(State state)

        {

            this.state = state;

        }

        public void Move()

        {

            state.Move(this);      

        }

        public void Attack()

        {

            state.Attack(this);           

        }

        public void Lucky()

        {

            state.Lucky(this);

        }

        public void CountDown()

        {

            state.CountDown(this);

        }

        public void SuperItem()

        {

            chageState(Superman.get_object);

        }

    }

}

 

 

마지막으로 파일관리 개체를 활용하는 모듈을 작성한다. 이때 모듈은 파일관리 개체의 상태에 전혀 신경을 쓰지 않아도 된다. 그냥 메서드를 호출하여 사용하기만 하면 된다.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace StatePattern

{

    class Program

    {

        static void Main(string[] args)

        {

            Character c = new Character();

           

            c.Attack();

            c.Attack();

            c.Attack();

            c.Move();

           

            c.Attack();

            c.Attack();

            c.Attack();

            c.Attack();

            c.Attack();

            c.SuperItem();

            c.Attack();

            c.Attack();

        }

    }

}

 





'Programing > Design Pattern' 카테고리의 다른 글

State Pattern (상태패턴)  (0) 2016.11.30
템플릿 메서드  (0) 2016.11.30
전략패턴,Strategy patterns  (0) 2016.11.30



우리는 게임이든다른 것이든 이런 객체의 상태에 대해서 많이 접하게 됩니다상태에 따라서 같은 기능도 다르게 작동해야 하는데 위 그림도 그것을 나타내고 있습니다만약 우리가 상태 패턴을 모른다면 두가지 방법밖에 없습니다상태가 정수로 표현된다면switch 문으로 case를 상태로 하여 쭈욱 늘어 뜨릴 수 있고상태가 정수가 아닌 문자열이나 기타 다른 조건이라면 if, else if로 복잡하게 코딩할 수 밖에 없습니다.






캐릭터 클래스의 모든 매서드의 처리를 상태객체에게 위임합니다위임된 기능은 상태 객체의 현재 타입에 따라 다르게 처리됩니다현재 타입이란 서브클래스 타입을 말하는 것이죠. 이 자체가 상태가 됩니다위임된 처리를 수행하는 방법은 캐릭터 클래스내에서 상태 객채를 접근 가능하게 한뒤상태 객체는 캐릭터 객체를 매개변수로 받아서 처리를 구현합니다이것은 마치 캐릭터 객체를 대신 해서 동작하는 느낌입니다상태를 바꿀때도 이런 방법을 사용합니다상태 객체는 내부 데이터 변수가 없기 때문에 싱글톤으로 만들어 여러 캐릭터 객체가 이 상태객체의 기능을 공유할 수 있습니다.*플라이급 패턴



'Programing > Design Pattern' 카테고리의 다른 글

상태패턴 예제  (0) 2016.11.30
템플릿 메서드  (0) 2016.11.30
전략패턴,Strategy patterns  (0) 2016.11.30

템플릿 메서드


 객체의 연산에는 알고리즘의 뼈대만을 정의하고 각 단계에서 수행할 구체적 처리는 서브클래스 쪽으로 미룹니다. 알고리즘의 구조 자체는 그대로 놔둔 채 알고리즘 각 단계처리를 서브클래스에서 재정의할 수 있게 합니다.


-GOF의 디자인패턴 중-











예를 들어 기존 커피와 차를 만드는 코드가 있는데 코코아를 만드는 코드를 만들게 되었습니다.이럴 경우 만드는 순서, 물을 끓이고 컵에 담는 동일 공정이 해야 할 것입니다.



하지만 템플릿 메서드를 사용 할 경우 동일 공정을 부모 클래스에 정의함으로써 코드의 중복과 하드 코딩을 방지 할 수 있습니다. 클래스는 부모클래스인 비버리지와 서브클래스인 커피와 티로 구성되며, 템플릿 메서드로는 음료제작에 대한 알고리즘의 골격을 정의하는 프리퍼레시피가 있습니다. 우선 부모클래스인 비버리지가 서브클래스인 커피와 티에 공통적인 행위에 대하여 정의하면, 자식클래스인 커피와 티는 서로 공통되지 않는 부분에 대하여 정의하고 있습니다. 또한 프로퍼레시피의 코디먼트는 첨가물여부에 대한 훅메소드로 구성되어 있습니다.


여기서 훅메소드는 부모 클래스에 선언되는 메소드이기는 하지만 기본적인 내용만 구현되어 있거나 아무 코드도 들어있지 않은 메소드 입니다. 이를 서브 클래스에서 선택적으로 오버라이드 하여 사용하며, 오버라이드 하지 않으면 부모클래스에서 기본으로 제공한 코드가 실행됩니다.


이러한 템플릿 메서드는 코드의 재사용성을 높일수 있다는점과 일부행동만 지정하는 프레임웍을 만다는데 유용하지만, 서브클래스가 꼭 구현해야할 매서드의 개수가 많아질수록 설계가 복잡해지고, 상속에 의존적이기 때문에 유연성이 떨어지는 단점이 있습니다.


관련패턴으로는 전략패턴이 있는데, 템플릿메서드는 동일알고리즘의 일부분이 다양한 형태를 띄도록 하기 위해 서브클래스에서 처리하고, 

전략패턴은 바꿔쓸수 있는 행동을 캡슐화하고, 어떤행동을 사용할지는 서브클래스에게 위임한다는 차이점이 있습니다. 


#include <iostream> 

 



using std::cout; 

using std::cin; 

using std::endl; 



class Beverage 

public: 

// 템플릿(틀) 메소드. 

// 알고리즘의 각 단계가 파생 클래스에서 수정되는 것을 방지하기 위해 비가상으로 선언.

// 비가상인터페이스 :  private 가상 함수를 감싸는 publice 비가상 함수(비가상 인터페이스)를 만들어 

// 인터페이스를 단일화하는 것을 의미

// 템플릿 메소드 패턴으로 구현

void PrepareRecipe() 

BoilWater(); 

Brew(); 

PourInCup(); 

if ( Condiments() ) // 후킹! 

AddCondiments(); 

}

}

private: 

// 모든 가상 메소드를 정의 해야만 한다.

//가상메소드 정의 (Brew & AddCondiments)

virtual void Brew()=0;

virtual void AddCondiments()=0;

// 후크연산 기본적으로 부모연산은 아무행동도 정의하지 않는다.

// 기본 클래스에 있는 템플릿 메소드의 알고리즘 단계에 파생 클래스가 여러가지 방식으로 개입할 수 있게 된다. 

virtual const bool  Condiments() 

{

return true; 

} //기본값 : 첨가물추가


void BoilWater() { cout << "물 끓이는 중" << endl; } 

void PourInCup() { cout << "컵에 따르는 중" << endl; } 

}; 



class Coffee: public Beverage 

private: 

// 가상메소드 재정의 (Brew & AddCondiments)

void Brew()

{

cout << "커피 우려내는중~"<<endl;

}


//행동확장을 위해 후크연산을 재정의한다.

virtual const bool Condiments() // 후크

cout << "설탕과 우유를 넣으시겠습니까? : 1. 네, 2. 아니오" << endl; 

int answer=0; 

bool res=0;


cin >>answer; 

if (answer ==1)

res = true; 

else if (answer ==2)

res = false;

return res; 

}

void AddCondiments()

{

cout << "우유와 설탕을 추가하는중~"<<endl; 

}

};



class Tea: public Beverage 

private: 

// 가상메소드 재정의 (Brew & AddCondiments)

void Brew()

{

cout << "티백 우려내는중~"<<endl;

}

void AddCondiments()

{

cout << "레몬을 추가하는중~"<<endl; 

}

};



void main()

{

Beverage *cafe = new Coffee();

cafe->PrepareRecipe();


delete cafe;


cout<<"\n\n"<<endl;


cafe = new Tea();

cafe->PrepareRecipe();


delete cafe;


cout<<"\n\n"<<endl;

cafe = new Coffee();

cafe->PrepareRecipe();


delete cafe;

}


'Programing > Design Pattern' 카테고리의 다른 글

상태패턴 예제  (0) 2016.11.30
State Pattern (상태패턴)  (0) 2016.11.30
전략패턴,Strategy patterns  (0) 2016.11.30

전략패턴



전략패턴의 핵심은 객체의 내부에서 나타날 수 있는 행동을 따로 분리하여 여러개로 확장하여 일일이 서브클래스마다 행동에 대한 하드코딩을 피한다는 것입니다.

하드코딩을 하지않는 대신생성자를 통해 매뉴얼(전략)을 선택하여 집어넣으면

끝입니다.


위 상황은 단순한 상황입니다이전 설계 할 때 모든 유닛 오브젝트는Att을 할꺼로 예상하고 베이스 오브젝트에 그 가상함수를 넣어놨습니다.

그리고 3개의 하위 클래스를 설계합니다. Marin,Medic,Tank 근데 문제가하나 있습니다. Medic은 예상을 벗어나 Att에 대한 행동을 정의할 수 없게 되었습니다해병은 총을 쏘고탱크는 캐논샷을 쏘지만 메딕은 공격을 하지 못합니다그래서 설계한 방법으로 베이스 클래스의 Att함수를 오버라이딩해서 {} 이렇게 빈칸으로 두기로 했습니다하지만 이런식으로 베이스 클래스의 가상함수가 늘어날수록 동작을 하지 않아야 되는 함수들을 일일이 오버라이딩으로 처리하여 코딩하는 것은 상당히 귀찮은 일입니다문법때문에 어쩔수 없다는 생각을 가져도 만약 1000개의 오브젝트에서 그런 하드코딩을 하라면….. 더불어 코딩이 실제로 들어가므로 유지보수때도 신경쓸 수 밖에 없습니다예를들어 베이스클래스의 기능이 10가지 인데 메딕은 그중에 3가지 밖에 쓰지 않는다고 가정해 봅시다그럼 나머지 7개를 빈칸으로 오버라이딩 할 수 밖에 없는 것이죠

이때 전략패턴을 사용하면 이런 수고를 덜 수 있을 뿐더러 다른 행동까지도 동적으로 정의할 수 있는 유연성이 생깁니다


위 그림에서 같이 전략패턴에서 전략을 나타내는 객체를 매뉴얼이라고 표현했습니다제가 생각하기에는 매뉴얼이 전략패턴의 컨셉과 잘 맞는것 같습니다전략 패턴의 핵심은 객체의 내부에서나타날 수 있는 행동을 따로 분리하여 여러 개로 확장하여 일일이 서브클래스마다 행동에 대한 하드코딩을 피한다는 것입니다하드코딩을 하지 않는 대신생성자를 통해 매뉴얼(전략)을 선택하여 집어넣으면 끝입니다위에서 Att함수는 그 내부에서 매뉴얼을 참조해서 행동하므로 다른 Att행동을 취할 수 있습니다만약 생성자에 매뉴얼을 넣지 않을때 Att함수는 아무일도 하지않게 설계하면 메딕을 생성하는데 문제가 없습니다





하나는 매개변수를 직접 마련하여 전달하는 형식이고 다른 하나는 객체 자신을 매개변수로 넘겨 접근권한을 주고 처리하게 하는 형식입니다전자는 매개변수 인터페이스에 맞춰서 전략객체의 기능을 사용하기때문에 매개변수를 위한 준비가 필요합니다그 인터페이스가 많은 서브클래스들을 고려하여 너무 복잡하다면 어떤 서브 객체에게는 쓰이지 않게 되는 매개변수가 생길 수도 있습니다.

후자는 매개변수에 객체 자신의 참조자를 넘겨 처리하는 방법입니다이는 상태패턴과 동일한 방법이라고 하는데요 본객체와 전략객체간의 겹합도가 높아지게 되는 방법이기도 한데 강결합으로해야 효율이 나올 수 밖에 없는 경우외에는 별로임

 

구구단 2 2단노트

 

– 결론-

 

전략패턴은 말그대로 객체의 전략을 런타임에 다르게 설정할 수 있게 해주는 패턴입니다.

객체안의 여러 매서드들에 대한 행동을 무한한 형태로 전략을 조합하여 변경할 수 있습니다.

행동 전체를 변경할 수도 있지만 행동에 쓰이는 알고리즘 하나만 변형하게 하여 성능의

향상을 꾀할 수도있습니다.


예제)

 #include <iostream>

using namespace std;

#define interface struct

interface Manual

{

virtual void Att() = 0;

};


class GunShot :public Manual

{

public : void Att()

{

cout << "따다다다당"<<endl;

}

};


class CanonShot : public Manual

{

public :

void Att()

{

cout <<"푸학 폭~!"<<endl;

}

};


class SteamPack : public Manual

{

public :

void Att()

{

cout <<"따다다다당 따다다다당 따다다다당~!"<<endl;

}

};


class Unit

{

Manual *_strategy;

public :

Unit(Manual *strategy=0)

{

_strategy = strategy;

}

virtual ~Unit() { }

void Att()

{

if(_strategy)

{

_strategy->Att();

}

}

virtual void Display() =0;

};

//*************************Marin*****************************

class Marine :public Unit

{

SteamPack *sp;

public :

Marine(Manual *ma) : Unit(ma)

{

sp = 0;

}

void SteamPackUpGrade()

{

if(sp == 0)

{

sp = new SteamPack();

}

}

void SteamPackAttack()

{

if(sp)

{

sp->Att();

}

}

~Marine()

{

if(sp)

{

delete sp;

}

}

public:

void Display()

{

}

};

//*************************Enginneer*****************************

class Medic :

public Unit

{

public:

Medic(Manual *ma=0) : Unit(ma){ }

public :

void Display()

{

}

};

//*************************Tank*****************************

class Tank:

public Unit

{

public :

Tank(Manual *ma) : Unit(ma) { }

public:

void Display()

{

}

};


void main()

{

Unit *unit = new  Marine(new GunShot);

unit->Att();


Marine *marine = dynamic_cast<Marine*>(unit);

marine->SteamPackUpGrade();

marine->SteamPackAttack();


Unit *unit2 = new  Tank(new CanonShot);

unit2->Att();


Unit *unit3 = new  Medic();

unit3->Att();

delete unit;

delete unit2;

delete unit3;

}


'Programing > Design Pattern' 카테고리의 다른 글

상태패턴 예제  (0) 2016.11.30
State Pattern (상태패턴)  (0) 2016.11.30
템플릿 메서드  (0) 2016.11.30

+ Recent posts