일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Trie
- PYTHON
- 프로그래머스
- 컨볼루션
- SWIFTUI
- backjoon
- leetcode
- 독서노트
- 전자공학
- 알고리즘문제풀이
- 백준
- Leet Coding Challenge
- leet code
- DTFT
- 이산신호처리
- 트라이
- IOS
- dft
- 코테
- 신호처리
- SWIFT
- 스위프트
- 릿코드
- 알고리즘
- 코딩테스트
- 코테준비
- 파이썬
- DSP
- 알고리즘 문제풀이
- 카카오 코딩테스트
- Today
- Total
매일 매일 성장하는 섭섭군
[Seop's 강의노트] MATLAB에서 Convolution 함수 구현 본문
저번학기에 이산신호에 관하여 배우면서 포스팅을 진행 하였지만
MATLAB을 사용하여 실습은 진행하지 않았다.
이번학기에 신호처리 실습을 배우는 만큰 어떻게 구현하는지에 대하여 글을 써보고자 한다.
신호처리와 관련해서 가장 먼저 한 실습은 컨볼루션과 관련된 실습이다.
신호처리 과목에서 컨볼루션은 가장 기본이 되는 만큼 가장 처음으로 진행한 것 같다.
MATLAB 코드와 함께 설명하는 방식으로 포스팅을 진행할 예정이다.
다만 코드인 만큼 주관적인 생각이 강하고 아직 필자가 MATLAB을 배우고 있는 초보적인
수준이라 잘 짠 코드라고는 말하기 힘들 것 같다.
본론으로 돌아가 Convolution 함수를 구현을 실행해 보자 컨볼루션 함수는 메틀랩에서 제공해 준다.
conv(x,h) 를 사용하면 된다.
하지만 우리는 위 함수를 사용하지 않고 함수를 직접 만들어 보고자 한다.
임의의 두 이산신호와 시간을 받아 출력신호, 출력 신호의 시간을 구해보고자 한다.
실습을 진행함에 있어서 고민해야 할 부분이 몇가지 있었다.
- 시간축의 시작점과 끝점을 설정하여 어떻게 시간축 출력을 설정할지?
- fliplr() 함수와 prod() 함수를 어떠한 방식으로 사용할지?
- 두 입력 신호의 길이가 다를 경우 어떻게 연산을 진행 할 것인지?
- 컨볼루션 연산을 위한 쉬프트 방식은 어떻게 구현할 것인지?
크게 위 4가지가 컨볼루션 함수를 구현하는데 해결야하 할 것들이었다.
이를 어떻게 해결하였는지에 대해서 살펴보도록 하겠다.
빠른 이해를 돕기 위하여 함수의 입출력을 설명하자면 다음과 같다.
입력
x , x_n : 첫번째 입력에 대한 시간과 신호
h, h_n : 두번째 입력에 대한 시간과 신호
출력
y, num : 출력에 대한 시간과 신호
- 시간축의 시작점과 끝점 설정하여 시간 축 출력 설정하기.
이 문제를 해결하기 위해서 우리는 두 입력신호 시간의 최소 값과
최대 값을 이용하기로 했다. 최소 값 두개를 더하여 시작하는 점을
설정하고 최대 값 두개를 더하여 끝점을 설정하는 것이다.
최소 값과 최대 값 사이값들을 구하기 위하여 개수를 센다.
그리고 linspace() 함수를 사용하여서 시간 축 출력 백터를 설정하였다.
구체적인 구현 코드는 다음과 같다.
위와 같은 방식으로 시간 축 출력 백터를 생성할 수 있었다.
- 두 입력 신호의 길이가 다를 경우 두 입력 신호 길이 맞춰주기.
입력신호의 값 두개의 길이가 다를 경우에는
매틀랩에서 연산이 되지 않는다. 그렇기 때문에 길이를 맞춰주는
작업을 진행하였다. 방법은 간단했다.
양 신호에 서로의 길이만큼 제로페딩 시켜주는 것이다.
즉 x 신호에는 h의 길이 만큼의 ‘0’ 값을 추가해 주고 h 신호에는 x 의 길이 만큼의 ‘0’을 추가시켜 주었다. 구제척인 구현 코드는 다음과 같다.
- 주어진 두 함수 fliplr() 과 prod()를
컨볼루션 연산에 사용하기.
주어진 두 함수 중 fliplr()을 어디에 사용해야 할지에 대해서는
큰 문제가 없었다.
다음 컨볼루션 기본식에서 두번째 신호에 사용하게 되면 n-k 를 해줄
필요 없이 연산이 가능하다. prod() 함수는 두 신호를 2행 행렬의 각 행에 집어 넣은 후에 사용하면 1차적인 컨볼루션 연산을 수행 할 수 있게 되어서 이때 사용 하였다. 이후 sum() 함수를 사용하여 그 값들을 더해 주면
한개의 출력 신호 값이 산출 된다. 구체적인 구현 코드는 다음과 같다.
위의 과정을 for 문 내에서 진행하게 하여 컨볼루션 연산을 진행할 수 있도록 하였다.
-컨볼루션 연산을 위한 쉬프트 방식 구현하기.
컨볼루션 연산은 한칸씩 밀리면서 연산을 진행한다고 생각 해 볼 수 있다. 그렇기 때문에쉬프트가 필요하다. 그리고 행렬 연산이기 때문에 각 백터의 개수 조정은 필수적이다. 이를 구현 하기 위해서
제로페딩을 진행시켜 주었다. 우리는 쉬프트 되어서 움직이는 신호를
X 로 설정하고 가만히 있는 신호를 fH 로 설정하였다.
움직이는 신호 X 에는 앞부분과 뒷부분 모두에 제로페딩을
진행시켜 주었다. 움직이지 않는 fH 신호에는 X 와 길이를 맞춰주기 위한
뒷 부분에만 제로페딩을 진행시켜 주었다.
구체적인 구현 코드는 다음과 같다.
위의 4가지 고민을 해결하면서 임의의 두 이산신호를 입력받아서 컨볼루션연산을 수행하는 함수를 만들 수 있었다.
'디지털신호처리, DSP' 카테고리의 다른 글
[Seop's 강의노트] 이산신호처리 _ DFT, Zero Padding (0) | 2019.10.23 |
---|---|
[Seop's 강의노트] 이산신호처리 _ DFT의 개념 (0) | 2019.10.23 |
[Seop's의 강의노트] LTI 시스템, 컨벌루션 이란? (0) | 2019.10.23 |
[Seop's 강의노트] 이산신호처리 _ DTFT의 특징 및 성질 (0) | 2019.10.23 |
[Seop's 강의노트] 이산신호처리 _ 표본화(Sampling) (0) | 2019.10.23 |