728x90

목표

- 캐닝 에지 컨샙 배우기

- cv2.Canny()함수 배우기

 

 

 

이론

- 캐니 에지 검출기는 많이 사용하는 에지 검출 알고리즘으로 196년 존 F 캐니가 만들었습니다. 이 캐니 에지 알고리즘은 여러 단계로 구성된 알고리즘으로 다음과 같습니다.

 

1. 노이즈 제거

- 에지 검출기는 어느정도 노이즈에 강인해야 하기때문에 첫 단계에서는 5 x 5크기의 가우시안 필터로 노이즈를 제거합니다. 이에 대해서 이전에 봤으니 넘어가겠습니다.

 

2. 이미지의 그라디언트 강도 계산하기

- 노이즈가 제거된 이미지는 그 다음에 소벨 커널로 수평과 수직 방향으로 필터를 적용하고 수평 방향에 대한 1차 미분 영상과 수직 방향에 대한 1차 미분 영상을 얻습니다.

- 이 두 영상을 가지고 에지 그라디언트와 방향을 얻을수 있게 됩니다

- 그라디언트 방향은 항상 에지에 수직이며, 수직, 수평 그리고 두 대각 방향 중 하나를 의미하는 값이라 할수 있겠습니다.

 

3. 비최대 억제 - non-maximum suppression

 그라디언트의 크기와 방향에 대한 정보를 얻으면 이제, 에지가 아닌 픽셀들을 제거하여야 합니다.

- 이 때, 모든 픽셀들은 그라디언트의 방향에 존재하는 이웃 점들과 비교하여 지역 최대점인지 확인하여야 합니다.

- 아래의 그림에서 A는 에지로(수직 방향에 대한), 그라디언트 방향은 에지와 돌일 합니다. 

- B,C는 그라디언트 방향에 존재하는데, 점 B, C가 지역 최대점인지 확인여야 하고 아닌 경우들은 0으로 놓습니다.

 

 

4. 가정 임계화 hysteresis Thresholding

- 이번 단계에서는 모든 에지가 실제 에지인지 아닌지 판단하여야 합니다. 여기서는 최소, 최대를 나타내는 임계값을 사용하겠습니다. 어느 에지가 maxVal보다 크면 에지, minVal보다 작으면 에지가 아니므로 버립니다.

- 이 두 임계치 사이에는 연결성을 이용해서 에지 여부를 판단하는데요. 사이에 존재하는 픽셀들이 확실히 에지인 것과 연결되어있다면 에지의 일부분으로 판단하고, 연결되지 않았다면 버리게 됩니다.

 

 

 

 

- 위 그림의 경우 에지 A는 최대값을 넘어가므로 확실한 에지가 됩니다. 에지 C의 경우에는 최대 값보다 밑에있으나 A에 연결되어 있으므로 이 또한 에지라고 판단합니다. 

- 하지만 에지 B의 경우 최소값은 넘어가지만 확실히 에지인것과 연결되어있지 않으므로 버립니다. 그래서 최대 최소 임계치를 잘 결정해야 올바른 결과를 얻을수가 있겠습니다.

 

 

 

 

 

 

케니 에지 검출기

 

 

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread("C:/Users/do/Documents/github/opencv_python/res/kimheungkook.jpg",0)
edges = cv2.Canny(img,100,200)

plt.subplot(121),plt.imshow(img,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])

plt.show()

 

300x250
728x90

전선의 종류

- 단선 : 가닥이 1가닥

- 연선 : 여러가닥

 

전선의 굵기

- awg 

- m m^2 : 단면적 넓이

- mm  :길이

 

전서 선태시 유의사항

 일반적인 회로에서 22awg, 0.5mm 0.3m m^2면 충분

- - 모터나 고전력 제품사용 시 굵은걸써야 안전적으로 전력 공급 가능

 

 

단선의 단점

- 브레드 보드에 좋음

- 단단해서 휘다보면 납댐부분이 부서질수 있음 -> 납댐시 단선 쓰면 안됨

 => 만능기판에 사용시 연선을 사용하자

 

 

점퍼 와이어

- 끝에는 핀으로 단선

- 가운데는 연선이 사용

=> 단선과 연선의 혼합

- ex. 암수, 암암, 수수 등의 다양하게 있음

- 단점 : 종류가 다양하지 않음.

=> 프로토타입시 점퍼와이어보다는 단선을 스트리퍼로 직접 잘라 만들어주는게 좋음

 

 

스트리퍼

- 와이어 스트리퍼 : 옆의 숫자는 awg amerage wage gage나 mm

- 자동 스트리퍼 : 굵기 상관없이 자름

 

전선과 케이블

- 전선 여러가닥이 있는경우

= > USB 케이블. 전선(연선)이 USB 2.0 4가닥, 3.0은 15가닥이 있음

 

 

 

analogWrite와 digitalWrite의 차이

- 아두이노를 만지면서 그동안 digitalWrite만 썻지 analogWrite는 거의 쓰질 않았던것 같았는데, analogWrite라는 함수가 있는걸 이제서야 알았다.

- 이름이 analogWrite라고 하니 핀에서 정현파 같은 아날로그 신호가 나오는건지 궁금했었는데 아날로그 신호가 아니라 PWM 신호가 나온다고 하더라.

- 디지털 라이트를쓸때는 해당 핀으로 0, 1만 나온다면

- 아날로그 라이트 할때는 PWM 출력이 나와 LED에서는 밝기 조절이 가능해지더라

 

 

 

300x250
728x90

 

앞으로 계속 내용 추가시켜나가자

 

 

 

 

300x250
728x90

간단하게 대학 수학을 훑어보면서

 

원래는 적분과 행렬에 대해서도 봐야되지만

 

 

행렬은 선형대수 공부하면서 많이 봤고

 

적분 파트는 미분 파트 보다는 덜 중요한것 같아 간단히 넘어갔다.

 

이번 주 중으로

 

대강 확률과 대학 수학을 훑어본듯하다.

 

 

확률을 보면서 어떤 분포와 함수들이 있는지, 모집단과 표본, 확률 과정등에 대해서보고

 

대학 수학을 통해 간단한 집합론부터 함수, 수열, 미분으로 마무리했다.

 

 

대강 최근한것들 하는중인거, 해야하나 안한거를 아래와 같이 정리할 수 있을거같다.

 

-------------1. 본거 -------------------

대학수학

확률

공업수학

선형대수

최적화론

---------------2. 하는 중 -------------

opencv-python

프로토타이핑

제어시스템

 

--------------3. 안본거 -------------

디지털신호처리

운영체제

통계

인공지능

다변량분석

 

 

opencv-python과 제어시스템은 디테일하게 하기에는 시간이 너무 오래걸릴것같아

 

적어도 opencv는 오늘부터 조금 간단하게 하려고한다.

 

 

아무튼 이번에 대학수학을 보고, 그동안 배운 내용들 덕분에

 

서울대 연구원분이 진행하시는 음성 합성 세미나 내용들이

 

완전히 이해할수는 없지만

 

그 동안 배운 개념들 조금조금씩 나오는게 너무 반가웠고

 

수학적 알고리즘을 어떻게 설계해서 실제 코딩으로 만들어나가는지

 

대략적인 느낌은 볼수 있었다.

 

 

영상처리와 음성 분야에 있어서

 

디지털 신호 처리가 많이 필요하니

 

시간 될때 좀 봐야할것 같다.

 

 

제어 시스템은 프로토타이핑 과정 때문에 정리하고 있는데

 

일단 제어 시스템은 조금 천천히 하고

 

opencv를 조금은 급하게 나가야할것 같다.

 

그래도 오늘 opencv 이미지 프로세스 내용의 절반 조금 안되는건 훑어봤으니 충분하겠지..

 

 

300x250
728x90

목표

- 이미지 그라디언트와 에지를 구해봅시다

 

이론

- opencv에서는 sobel, scharr, laplacian 3가지 그라디언트 필터(고주파 통과 필터)를 제공하고 있습니다.

 

 

1. sobel과 shcarr 미분 

- 소벨 연산자는 결합 가우시안 스무딩 + 미분을 수행하므로 노이즈에 강인하나, 미분 방향과 커널 크기를 명시해주어야 합니다.

- scharr 필터는 소벨 필터보다 더 좋은 결과를 내는데 한번 보세요

 

2. 라플라시안 미분

- 이미지 라플라시안을 구하려면 다음의 식을 계산하면 됩니다. 여기서 각각의 미분은 소벨과 동일하게 수행해서 얻을수 있겠습니다.

 

- ksize = 1로 하는 경우 다음의 커널이 필터링에 사용되겠습니다.

 

 

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('C:/Users/do/Documents/github/opencv_python/res/dave.jpg', 0)

laplacian = cv2.Laplacian(img,cv2.CV_64F)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)

plt.subplot(2,2,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,2),plt.imshow(laplacian,cmap = 'gray')
plt.title('Laplacian'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,3),plt.imshow(sobelx,cmap = 'gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,4),plt.imshow(sobely,cmap = 'gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])

plt.show()

 

 

 

300x250
728x90

목표

- 침식 erosion, 팽창 dilation, 열림, 닫힘 등 다양한 모폴로지 연산을 사용해봅시다.

 

이론

- 모폴로지 연산은 이미지 형태를 이용한 단순한 연산이라고 할수 있습니다.

- 보통 2진 이미지를 가지고 하는데요.

- 입력은 2개로, 하나는 원본 영상, 그리고 연산 종류를 결정하는 커널(구조 요소)가 됩니다.

- 기본적은 두가지 모폴로지 연산은 침식과 팽창 연산이 있습니다.

- 이들을 이용해서 열림과 닫힘, 그라디언트 같은 연산을 수행할수 있게 됩니다.

 

 

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('C:/Users/do/Documents/github/opencv_python/res/j.png')

kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1)
dilation = cv2.dilate(img,kernel,iterations = 1)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

plt.subplot(231),plt.imshow(img),plt.title('origin')
plt.xticks([]), plt.yticks([])
plt.subplot(232),plt.imshow(erosion),plt.title('erosion')
plt.xticks([]), plt.yticks([])
plt.subplot(233),plt.imshow(dilation),plt.title('diliation')
plt.xticks([]), plt.yticks([])
plt.subplot(234),plt.imshow(opening),plt.title('opening')
plt.xticks([]), plt.yticks([])
plt.subplot(235),plt.imshow(closing),plt.title('closing')
plt.xticks([]), plt.yticks([])
plt.subplot(236),plt.imshow(gradient),plt.title('gradient')
plt.xticks([]), plt.yticks([])

plt.show()

 

 

 

300x250
728x90

목표

- 다양한 저주파 통과 필터로 이미지를 뿌옇게 마만들어 봅시다.

- 2차원 콘볼루션을 통해 커스텀 필터를 사용해봅시다.

 

 

2차원 컨벌루션과 필터

- 1차워 신호의 경우 이미지는 다양한 저주파 통과 필터 LPF Low Pass Filter나 고주파 통과 필터 HPF High Pass Filter로 필터링을 할수 있습니다.

- LPF는 노이즈를 제거해주고 영상을 흐리게 만들어 줍니다.

- HPF는 이미지에 존재하는 에지를 찾는데 도와줍니다.

 

 

평균 필터

-opencv에서는 이미지를 커널(마스크)로 컨벌루션할수 있게 cv2.filter2D()함수를 제공하는데요.

- 영상에 평균 필터를 적용해본다면 5x5 크기의 평균 필터 커널은 아래와 같이 정의할수도 있겠습니다.

 

 

필터 수행

- 각 픽셀에 5 x5 크기의 윈도우(필터, 마스크)가 중간에 그 픽셀이 위치하도록 놓고 25개의 필터와 원본 영상의 값들을 곱한 후 합하여 새 영상에 그 픽셀 자리에 컨벌루션한 결과 합을 넣어줍니다.

- 이렇게 윈도우 내부에서 픽셀들의 평균 값이 계산 되며, 모든 픽셀들에 수행하면 필터링된 결과 이미지를 얻게 됩니다.

- 한번 다음 코드를 돌려보세요.

 

 

 

 

 

 

 

 

 

이미지 블러링(이미지 스무딩)

- 이미지 블러링은 저주파 통과 필터를 영상에다가 컨벌루션하여 얻을수 있습니다.

- 이는 노이즈 제거에 좋은 방법이라할수 있는데요.

- 고주파 성분들(노이즈, 에지)들을 영상에서 제거하여 필터링된 결과 블러된 이미지를 얻게 됩니다.

- OPENCV에선 4가지의 블러링 기술들을 제공하고 있어요.

 

 

 

1. 평균 블러링

- 이미지를 정규화된 박스 필터로 컨볼루션해서 얻을수 있습니다.

- 커널 영역에서 모든 픽셀들의 평균을 구하는 방식으로, 이 평균값으로 해당 픽셀의 값을 바꿔줍니다.

- 여기서 사용하는 함수는 cv2.blur()나 cv2.boxFilter()를 사용하며, 3x3크기의 정규화박스 필터는 아래와 같습니다.

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('C:/Users/do/Documents/github/opencv_python/res/opencv_logo.png')

blur = cv2.blur(img,(5,5))

plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()

 

 

 

 

 

 

2. 가우시안 블러링

- 이번에는 필터의 모든 계수들이 동일한 박스 필터 대신에 가우시안 필터를 사용해보겠습니다.

- 가우시안 필터는 cv2.GaussianBlur()함수로 사용할수 있는데, X와 Y방향에 표준 편차를 지정해주어야 합니다.

 * 0을 주면 필터 크기로 알아서 주고, sigma X만 명시하는경우 Y도 동일하게 적용됩니다.

- 가우시안 필터는 영상 내부의 가우시안 노이즈를 제거하는대 유용합니다.

 

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('C:/Users/do/Documents/github/opencv_python/res/opencv_logo.png')

blur1 = cv2.GaussianBlur(img,(5,5),0)
blur2 = cv2.GaussianBlur(img,(15,15),0)
blur3 = cv2.GaussianBlur(img,(15,15),10)

plt.subplot(221),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(222),plt.imshow(blur1),plt.title('Blurred 1')
plt.xticks([]), plt.yticks([])
plt.subplot(223),plt.imshow(blur2),plt.title('Blurred 2')
plt.xticks([]), plt.yticks([])
plt.subplot(224),plt.imshow(blur3),plt.title('Blurred 3')
plt.xticks([]), plt.yticks([])
plt.show()

 

 

 

 

 

 

 

 

 

300x250
728x90

목표

-단순 이진화, 적응적 이진화, 오츠 이진화

 

 

단순 이진화

- 이진화는 간단하게 임계값보다 크다면 1, 아니면 0을 주는 간단한 문제

 -> cv2.thresold 함수 사용. 명암영상만 가능

- 둘째 매개변수는 이진화에 사용할 임계값.

- 3번째 매개변수는 픽셀의 최대값

- 냇쨰 파라미터로 아래와 같은 것들이 있음.

   cv2.THRESH_BINARY

   cv2.THRESH_BINARY_INV

   cv2.THRESH_TRUNC

   cv2.THRESH_TOZERO

   cv2.THRESH_TOZERO_INV

 

 

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('C:/Users/do/Documents/github/opencv_python/res/gradient.png',0)
ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)

titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

for i in xrange(6):
    plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

plt.show()

 

1. 원본 영상 

2. 이진화 : 명암값 127 기준으로

3. 역이진화 : 127보다 작으면 1

4. truc : 127보다 작으면 0

...

 

 

 

 

 

 

 

적응적 이진화

- 조금전 예제에선 임계치값을 지정해줌

- 빛이 비쳐 그늘 생긴 이미지에선 안좋음 -> 적응적 이진화 사용

- 영상 일부분을 서로 다른 이진화 값 사용 -> 모든 영역에 다른 이진화 값을 적용하여 조명 변화시에도 좋은 결과 나옴

 

적응적 이진화 파라미터

- 적응화 방법

   cv2.ADAPTIVE_THRESH_MEAN_C : 주위 영역의 평균값을 임계치로 사용

   cv2.ADAPTIVE_THRSH_GAUSSIAN_C : 가우시안 윈도우로 주위 픽셀들의 가중치 합을 임계치로 사용

- BLOCK SIZE : 주변 공간 크기

- C : 상수로 평균과 가중치에서 얼마만큼 -할지 지정하는값

* 반환값 ret은 나중에 설명

 

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('C:/Users/do/Documents/github/opencv_python/res/dave.jpg',0)
img = cv2.medianBlur(img,5)

ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,\
            cv2.THRESH_BINARY,11,2)
th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
            cv2.THRESH_BINARY,11,2)

titles = ['Original Image', 'Global Thresholding (v = 127)',
            'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]

for i in range(4):
    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

 

 

 

 

 

 

 

 

오츠 이진화

- 이전에 살펴본 전역적인 이진화에선 특정한 임계값을 사용

  => 이 임계값이 좋은지 나쁜지 알려면 시행착오(trial and error)를 해야함

- 하지만 양봉 이미지(히스토그램상 봉우리가 2개인) 경우를 생각해보면 양 봉우리의 평균을 근사해서 임계치를 사용해야함 -> 오츠 이진화가 수행

 => 이미지 히스토그램으로 자동으로 임계치 계산 해줌

 

오츠 이진화 코드

- cv2.threshold() 함수를 사용. 플래그 cv2.THRESH_OTS 추가. 임계값은 0으로 설정

- 다음 예시에서 노이즈 영상 사용

- 1번째 케이스는 전역 임계치를 127로 설정

- 2번째는 오츠 이진화를 바로 수행

- 셋째는 5 x5 가우시안 커널로 노이즈 제거후 오츠 이진화 수행

 

 

 

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('C:/Users/do/Documents/github/opencv_python/res/noisy2.png',0)

# global thresholding
ret1,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)

# Otsu's thresholding
ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# Otsu's thresholding after Gaussian filtering
blur = cv2.GaussianBlur(img,(5,5),0)
ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# plot all the images and their histograms
images = [img, 0, th1,
          img, 0, th2,
          blur, 0, th3]
titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)',
          'Original Noisy Image','Histogram',"Otsu's Thresholding",
          'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]

for i in range(3):
    plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
    plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
    plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
    plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([])
    plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')
    plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([])
plt.show()

 

 

 

 

 

 

 

오츠 이진화 동작 방법

- 양봉 이미지에서 오츠 이진화를 수행할떄, 오츠 알고리즘은 두 가중화된 클래스의 분산을 최소화 하는 임계치를 찾음

 

 

=>  두 클래스의 분산이 최소가 되는 값 t를 찾게됨

- 위 식을 아래와 같이 구현할 수 있다.

 

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('C:/Users/do/Documents/github/opencv_python/res/noisy2.png',0)
blur = cv2.GaussianBlur(img,(5,5),0)

# find normalized_histogram, and its cumulative distribution function
hist = cv2.calcHist([blur],[0],None,[256],[0,256])
hist_norm = hist.ravel()/hist.max()
Q = hist_norm.cumsum()

bins = np.arange(256)

fn_min = np.inf
thresh = -1

for i in range(1,256):
    p1,p2 = np.hsplit(hist_norm,[i]) # probabilities
    q1,q2 = Q[i],Q[255]-Q[i] # cum sum of classes
    b1,b2 = np.hsplit(bins,[i]) # weights

    # finding means and variances
    m1,m2 = np.sum(p1*b1)/q1, np.sum(p2*b2)/q2
    v1,v2 = np.sum(((b1-m1)**2)*p1)/q1,np.sum(((b2-m2)**2)*p2)/q2

    # calculates the minimization function
    fn = v1*q1 + v2*q2
    if fn < fn_min:
        fn_min = fn
        thresh = i

# find otsu's threshold value with OpenCV function
ret, otsu = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
print(thresh)
print(ret)

 

 

오츠 이진화 알고리즘 수행과정 

- 수식 

1. 이미지 읽고 블러링

 

2. 히스토그램을 구하고, 정규화 후 누적 확률 분포(위 식에서 q) 얻기

3. 이진화 구간, 파라미터 설정

4. i 값에 따라 정규화 히스토그램, 누적합, 이진화 구간 분리

 

5. 4에서 구한 확률들과 두 클래스의 누적확률분포, 이진화 구간(가중치로 사용)으로 기대값 계산

 

6. 오츠 임계화에 필요한 omega^2구하기

 - [가중치(이진 구간) - 기대값]^2 * i일 확률 / 누적확률분포

 

 

 

7. 오츠 최소화 함수 계산

- 모든 픽셀에 대해 루프 돌면서, 비용 함수가 최소가 될때 오츠값(ft_min)과 임계치(thresh)를 구함

 

300x250
728x90

목표

- 이미지를 가지고 기하학적 변환을(평행이동, 회전, 어파인 등) 해봅시다.

 

대표적인 기하학적 변환 함수

-opencv에서 대표적으로 2가지 변환 함수 제공

- cv2.warpAffine : 어파인 변환= 평행이동 + 회전+ 스케일링

- cv2.warpPerspective : 원근 변환 = 평행 이동 + 회전 + 스케일링 + 원근

 

 

스케일링 변환

- 이미지 크기 조절 -> cv2.resize()

- 사용되는 보간법 -> ex. cv2.INTER_AREA(크기 줄일때), cv2.INTER_CUBIC or cv2.INTER_LINEAR(크기 늘릴떄)

 

파일명 : 01_scaling.py

- 원본 이미지 2배로 늘림. INTER_CUBIC 보간법 사용

import cv2
import numpy as np

img = cv2.imread("C:/Users/do/Documents/github/opencv_python/05day/kimheungkook.jpg")

height, width = img.shape[:2]
res = cv2.resize(img,(2*width, 2*height), interpolation = cv2.INTER_CUBIC)
cv2.imshow('image1',img)
cv2.imshow('image2',res)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

 

평행이동 변환

- 이미지를 밀어내는 변환

- (x. y) 좌표계 상에서 (t_x, t_y)만큼 이동시키는 변환 행렬 M은 아래와 같음

=> cv2.warpAffine() 함수에 매개변수로 넣어 100,50 정도 이동

 

- x축으로 100, y축으로 50 만큼 이동

import cv2
import numpy as np

img = cv2.imread("C:/Users/do/Documents/github/opencv_python/05day/kimheungkook.jpg", 0)

rows,cols = img.shape

M = np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img,M,(cols,rows))
cv2.imshow('img',img)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

 

 

 

회전 rotation 변환

- 각도 theta만큼 이미지를 회전시키는 변환 행렬 M은 아래와 같음

- 하지만 opencv는 중심점을 지정해서 회전 가능

- cv2.getRotationMatrix2D 함수로 위와 같은 회전 변환 행렬을 얻을 수 으며 스케일링 없이 90도 회전한 결과는 아래와 같음

 

import cv2
import numpy as np

img = cv2.imread("C:/Users/do/Documents/github/opencv_python/05day/kimheungkook.jpg", 0)
rows,cols = img.shape

M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv2.warpAffine(img,M,(cols,rows))
cv2.imshow('img',img)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

 

 

 

 

 

 

어파인 변환

- 어파인 변환에서 원근 변형은 생기지 않음.

- 이 변환을 하려면 입력 영상에서 3점과 출력 영상에서 대응할 점 3개를 지정해야함

- cv2.getAffineTransform 함수로 2 x 3 행렬을 만들어 cv2.warpAffine 수행

 * 어파인 변환= 회전, 평행이동, 스케일링이 수행됨

 

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("C:/Users/do/Documents/github/opencv_python/05day/kimheungkook.jpg")
rows,cols,ch = img.shape

pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[100,24],[80,200]])

M = cv2.getAffineTransform(pts1,pts2)

dst = cv2.warpAffine(img,M,(cols,rows))

plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()

 

 

 

 

원근변환 perspective transform - 기울어진 사진을 펴기

- 원근 변환 시에는 3 x3의 변환 행렬이 필요합니다. 이 행렬을 구하기 위해선 입력 이미지의 4개의 점과 출력 영상에서 4점이 필요하며, cv2.getPerspectiveTransform 함수로 얻을 수 있습니다.

- 그러고 나서 cv2.warpPerspective 함수로 아까 구한 변환 행렬을 사용하면 원근 변환된 이미지를 얻게 됩니다.

 

 

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("C:/Users/do/Documents/github/opencv_python/05day/kim_perspective.png")
rows,cols,ch = img.shape

pts1 = np.float32([[11,5],[592,17],[512,438],[90,440]])
pts2 = np.float32([[0,0],[592,0],[592,442],[0,442]])

M = cv2.getPerspectiveTransform(pts1,pts2)

dst = cv2.warpPerspective(img,M,(592,442))


cv2.imshow('img',img)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

- 아래의 사진은 원본 이미지로 592 x 442 크기

- 기존 모서리 : (11,5), (592. 17), (512, 438), (90, 440)

- 변경 후 모서리 : (0,0) (592, 0), (592, 442), (0, 442)

 

300x250
728x90

 

 

평균 변화율과 순간 변화율, 법선

- 평균 변화율 = 할선 scant line의 기울기 slope of secant

- 순간 변화율 = 접선 tangent line 의 기울기 slope of tangen

- 법선 normal line: 접선과 수직인 선

 

https://m.blog.naver.com/PostView.nhn?blogId=miseos&logNo=221233704901&proxyReferer=https%3A%2F%2Fwww.google.com%2F

 

 

 

 

평균값 정리

- 함수 y = f(x)가 닫힌 구간 [a, b]에서 연속이고 (a, b)에서 미분 가능한 경우 아래의 식을 만족하는 c가 (a, b) 사이에 적어도 한개가 존재

 

$\frac{f(b) - f(a)} {b - a}$ = f'(c) 

 

 

 

 

 

극댓값, 극솟값, 극값

1. 극댓값 local maximum

 -열린구간 I에서 f(c)가 최대값인 경우 f(c)는 극댓값, x = c에서 f(x)는 극댓값 가짐

2. 극솟값 local maximum

 - 열린구간 I에서 f(c)가 최소값인 경우 f(c)는 극속값, x = c에서 f(x)는 극솟값이됨

3. 극값 local extrema

 - 극솟값 혹은 극댓값

=> 아래의 그림은 전역 극대점, 전역 극소점, 지역 극대점, 지역 극소점을 나타냄

https://en.wikipedia.org/wiki/Maxima_and_minima

 

 

 

 

 

최적화 문제

- 최대값이나 최소값을 구하는 문제

 

최소 자승법 least square method : LSM

- 에러 제곱 합 sum of squared error을 최소로하는 해를 구하는 방법

 => 점과 직선사이에 오차가 가장 작도록 하는 직선을 구할 시 사용

 

https://en.wikipedia.org/wiki/File:Least_Squares.gif

 

 

 

미소 증분과 선형 근사

- 미소 증분 $\Delta x$가 충분히 작다면 dx(미분)이 되며, 아래와 같이 정리 가능

  $\Delta_y$ = f(a + $\Delta_x$) - f(a) $\approx$ f'(a) $\Delta$ x

 

- a + $\Delta_x$ = x로 하면 다음과 같이 x = a에서의 직선의 방정식을 선형 근사하여 얻을 수 있다.

f(x) $\approx$ f'(a) (x - a) + f(a)

 => 직선이 아닌 n차에 대한 근사로 테일러 전개가 있음.

 

 

수치미분 numerical defferential

- 미분 공식으로 도함수를 얻을수 있으나, 미분 계수 근사값만으로도 충분할수도 있음.

- x = a에서의 미분 계수와 미소 증분이 충분히 작은 경우 평균 변화율(할선의 기울기)과 순간 변화율(점선의 기울기)은 비슷

 

순간 변화율(미분 계수) : f'(a) = $lim_{\Delta x -> 0} \frac{f(a + \Delta x)  - f(a) } {\Delta x}$

 

평균 변화율(미소 증분이 작은 경우) : f'(a) $\approx$ $\frac{f(a + \Delta x) - f(a)} {\Delta x}$

 

 

뉴턴 방법 netwon method

- 4차 방정식부터 근의 공식이 존재하지 않음

- n차 함수 f(x) = 0인 경우의 해를 어떻게 구할까?

1. x= a1에서 접선을 구함. 이 접선의 x 절편을 a2

   y - $f(a_1) = f'(a_1) (x - a_1)$

   $a_2$ = $a_1$ - $\frac{f(a_1)} {f'(a_1)}$

2. x = a2에서 접슨을 구함. 얻은 접선의 x절편 a3

....

=> f(x) $\approx$ 0인 x를 구하게 됨.

   $a_{n + 1}$ = $a_{n}$ - $\frac{f(a_n)} {f'(a_n)}$

 

$lim_{n -> \infty} a_n$ = $\alpha$

 

- f($\alpha$) = 0

- 아래는 뉴턴 방법으로 f(x) = 0이되는 x= $\alpha$를 뉴턴 방법으로 구하는 과정

https://medium.com/@ruhayel/an-intuitive-and-physical-approach-to-newtons-method-86a0bd812ec3

 

 

 

경사법 gradient method

- 목적 함수, 비용 함수를 정의하여 이 비용이 최소(극소)가 되는 방향으로 내려가는 방법

- 보폭크기 $\alpha$만큼 경사 방향으로 내려감

https://medium.com/diogo-menezes-borges/what-is-gradient-descent-235a6c8d26b0

 

300x250

'수학 > 수학, 수치해석' 카테고리의 다른 글

대학수학 - 6. 미분  (0) 2020.08.10
대학수학 - 5. 수열  (0) 2020.08.10
대학수학 - 4. 수학과 컴퓨터 과학의 분야  (0) 2020.08.07
대학수학 - 3. 집합  (0) 2020.08.07
대학수학 - 2. 수학의 개요  (0) 2020.08.06

+ Recent posts