728x90
2021/02/23 - [기록 note] - 2021-02-23(OpenCV_5)
### Sobel2
import sys
import numpy as np
import cv2
'''
src = cv2.imread('lenna.bmp', cv2.IMREAD_GRAYSCALE)
if src is None:
print('Image load failed!')
sys.exit()
dx = cv2.Sobel(src, cv2.CV_32F, 1, 0)
dy = cv2.Sobel(src, cv2.CV_32F,0, 1)
cv2.imshow('src', src)
cv2.imshow('dx', dx) #imshow는 입력받는 변수가(dx,dy) 플롯타입이면, 128을 곱해서 보여준다 즉, 포화상태가된다
cv2.imshow('dy', dy)
cv2.waitKey()
cv2.destroyAllWindows()
'''
# ===================================================
'''
src = cv2.imread('lenna.bmp', cv2.IMREAD_GRAYSCALE)
if src is None:
print('Image load failed!')
sys.exit()
dx = cv2.Sobel(src, cv2.CV_32F, 1, 0)
dy = cv2.Sobel(src, cv2.CV_32F,0, 1)
#dx,dy라는 미분 행렬을 이용해서 magnitude(크기), 즉 미분값(변화량)의 크기를 보여준다.
mag = cv2.magnitude(dx,dy) #이상태에서는 mag도 float 형태가된다 => 제대로 볼수가 없다. imshow에서 포화상태가 되기 때문에
#mag 크기가 255보다 커질수가 있기 때문에 saturate적용
mag = np.clip(mag, 0,255).astype(np.uint8)
"""
왼쪽기둥보면 변화량 표현이 잘 되어있다. dx와 dy가 합쳐진 결과이다
밝은 부분은 엣지가 강하고
검정 부분은 엣지가 있지만 약한 부분
"""
cv2.imshow('src', src)
cv2.imshow('src', mag)
cv2.waitKey()
cv2.destroyAllWindows()
'''
# ====================================================
src = cv2.imread('lenna.bmp', cv2.IMREAD_GRAYSCALE)
if src is None:
print('Image load failed!')
sys.exit()
dx = cv2.Sobel(src, cv2.CV_32F, 1, 0)
dy = cv2.Sobel(src, cv2.CV_32F,0, 1)
mag = cv2.magnitude(dx,dy)
mag = np.clip(mag, 0,255).astype(np.uint8)
#mag를 이용해서 엣지부분을 뽑을수 있다.
# 1. 검정색으로 채워진 엣지 부분을 하나 만든다
edge= np.zeros(mag.shape[:2], np.uint8)
# 2.픽셀값이 120보다 큰 값만 255로 확 밝게 바꾼다
edge[mag>120]=255 #불리언 인덱싱, threshhold 값 120
cv2.imshow('src', src)
cv2.imshow('mag', mag)
cv2.imshow('edge', edge)
cv2.waitKey()
cv2.destroyAllWindows()
### 소베필터
import sys
import numpy as np
import cv2
src = cv2.imread('lenna.bmp', cv2.IMREAD_GRAYSCALE)
if src is None:
print('Image load failed!')
sys.exit()
#직접 구현
'''
kernel_x=np.array([
[-1,0,1],
[-2,0,2],
[-1,0,1]], dtype= np.float32)
kernel_y= np.array([
[-1,-2,-1],
[0,0,0],
[1,2,1]], dtype =np.float32)
dx= cv2.filter2D(src, -1, kernel_x)
dy= cv2.filter2D(src, -1, kernel_y)
'''
'''
좌측 상단을 보면, 밝은 픽셀에서 어두운 픽셀로 급 감소로 한 변화량을
보였다. 급 감소한 변화량은 음수로 표현이 되는데 이는 saturate 되어서 0으로 바뀐다
그래서 화면을 보게되면 변화가 있음에도 불구하고 검정색으로 표현이 된다.
그레이스케일로 표현하다 보니까 saturate가 된다.
해결방법 중 하나는 추가적인 값을(delta) 더해준다 보통 128
'''
# 해결방법1
# 회색은 값 변화량이 크지 않은부분,
# 검정색 부분은 값이 급격하게 감소한 부분
# 하얀색 부분은 값이 급격하게 증가한 부분
# dx= cv2.filter2D(src, -1, kernel_x, delta=128)
#ddepth=-1(입력영상과 같은 타입)
#dx=1, dy=0
dx = cv2.Sobel(src, -1, 1, 0, delta=128)
#dx=0, dy=1
dy = cv2.Sobel(src, -1, 0, 1, delta=128)
'''
dx,dy 왼쪽 기둥부분을 보면
x방향에는 기둥이 보이지만 dy에는 보이지 않는다
왜냐면, x방향기준에는 값의 변동이 있지만 y방향기준에서 볼때는 변동으로
보이지 않기 때문
'''
cv2.imshow('src', src)
cv2.imshow('dx', dx)
cv2.imshow('dy', dy)
cv2.waitKey()
cv2.destroyAllWindows()
## canny
import sys
import numpy as np
import cv2
src = cv2.imread('building.jpg', cv2.IMREAD_GRAYSCALE)
if src is None:
print('Image load failed!')
sys.exit()
#src: 컬러영상도 가능하지만 일반적으로는 그레이스케일사용한다
#컬러영상 3채널을 모두 미분계산 한 다음에 가장 최대값을 적용한다
dst = cv2.Canny(src, 100, 150)
cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
### 허프변환
import sys
import numpy as np
import cv2
src = cv2.imread('building.jpg', cv2.IMREAD_GRAYSCALE)
if src is None:
print('Image load failed!')
sys.exit()
edges = cv2.Canny(src, 50, 150) #캐니 엣지 검출기
#임계값 160, rho 값은 1 픽셀 ,각도 값은 1도단위로, threshold 160
lines = cv2.HoughLinesP(edges, 1, np.pi / 180., 160,
minLineLength=50, maxLineGap=5)
#컬러변환을 해야지 빨간성분의 선분(0,0,255)을 표현할수가 있다
dst = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)
if lines is not None: #직선이 없을수도 있음
for i in range(lines.shape[0]): #lines.shape[0]: 직선성분의 갯수
#x , y
pt1 = (lines[i][0][0], lines[i][0][1]) # 시작점 좌표
#x , y
pt2 = (lines[i][0][2], lines[i][0][3]) # 끝점 좌표
cv2.line(dst, pt1, pt2, (0, 0, 255), 2, cv2.LINE_AA)
cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
### 허프변환 원
import sys
import numpy as np
import cv2
# 입력 이미지 불러오기
src = cv2.imread('dial.jpg')
if src is None:
print('Image open failed!')
sys.exit()
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
blr = cv2.GaussianBlur(gray, (0, 0), 1.0)
def on_trackbar(pos):
rmin = cv2.getTrackbarPos('minRadius', 'img')
rmax = cv2.getTrackbarPos('maxRadius', 'img')
th = cv2.getTrackbarPos('threshold', 'img')
circles = cv2.HoughCircles(blr, cv2.HOUGH_GRADIENT, 1, 50,
param1=120, param2=th, minRadius=rmin, maxRadius=rmax)
dst = src.copy()
if circles is not None:
for i in range(circles.shape[1]):
cx, cy, radius = circles[0][i]
print(cx, cy, radius)
cv2.circle(dst, (cx, cy), radius, (0, 0, 255), 2, cv2.LINE_AA)
cv2.imshow('img', dst)
# 트랙바 생성
cv2.imshow('img', src)
cv2.createTrackbar('minRadius', 'img', 0, 100, on_trackbar)
cv2.createTrackbar('maxRadius', 'img', 0, 150, on_trackbar)
cv2.createTrackbar('threshold', 'img', 0, 100, on_trackbar)
#트랙바 초기값
cv2.setTrackbarPos('minRadius', 'img', 10)
cv2.setTrackbarPos('maxRadius', 'img', 80)
cv2.setTrackbarPos('threshold', 'img', 40)
cv2.waitKey()
cv2.destroyAllWindows()
### 동전계산 실습
import sys
import numpy as np
import cv2
# 입력 이미지 불러오기
src = cv2.imread('coins1.jpg')
if src is None:
print('Image open failed!')
sys.exit()
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
blr = cv2.GaussianBlur(gray, (0, 0), 1) #HoughCircle는 노이즈에 민감하기때문에 블러를 사용해서 노이즈제거 한다
# 허프 변환 원 검출
circles = cv2.HoughCircles(blr, cv2.HOUGH_GRADIENT, 1, 50,
param1=150, param2=40, minRadius=20, maxRadius=80)
# 원 검출 결과 및 동전 금액 출력
sum_of_money = 0
dst = src.copy()
if circles is not None: #원이 하나라도 검출이 됐을경우
for i in range(circles.shape[1]): # 원에 대한 정보를 추출, 총 11개
cx, cy, radius = circles[0][i] #반지름은 radius, 중심좌표 cx,cy
cv2.circle(dst, (cx, cy), int(radius), (0, 0, 255), 2, cv2.LINE_AA)
# 동전 영역 부분 영상 추출
#실수형을 정수형으로 컨버젼
x1 = int(cx - radius) # 원의 맨 좌측(좌)
y1 = int(cy - radius) # 원의 맨 아래(상)
x2 = int(cx + radius) # 원의 맨 우측(우)
y2 = int(cy + radius) # 원의 맨 위 (하)
radius = int(radius)
# 동전 영역 부분 영상을 입력영상에서 짤라낸다
crop = dst[y1:y2, x1:x2, :] #3채널 모두에 적용
ch, cw = crop.shape[:2]
cv2.imshow('crop',crop)
print(crop.shape)
print(ch,cw)
# 동전 영역에 대한 ROI 마스크 영상 생성
# 히스토그램을 그리기 위한 mask
mask = np.zeros((ch, cw), np.uint8) #crob과 동일한 크기의 검정색 형태로 일단 만든다
# cv2.imshow('mask',mask) #검정색 바탕만 보임
cv2.circle(mask, (cw//2, ch//2), radius, 255, -1) #반지름 radius을 중심으로 안을 채우는 흰색(255)으로 만든다
cv2.imshow('mask',mask)
cv2.waitKey()
# 동전 구분을 위한 색 성분 작업
# 동전 영역 Hue 색 성분을 +40 시프트하고, Hue 평균을 계산
hsv = cv2.cvtColor(crop, cv2.COLOR_BGR2HSV) #crop은 컬러 이며, 동전이 들어갈만한 사각형 크기로 짤려 있고 빨간색 테두리가 있는 영상을 HSV로 변환
hue, _, _ = cv2.split(hsv) #색 성분 추출
#십원짜리 동전의 히스토그램이 180근방에서 나왔기때문에 shift 진행
#180보다 큰 값은 0근방으로 보내기 위해서 나머지 나눗셈 % 사용
#결론, 십원짜리는 0~50 픽셀, 백원은 140~160 픽셀을 가지는 값을 갖게된다
#현재 hue_shift에는 동전 뿐만 아니라 사각형의 모서리까지 픽셀 40을 더해졌다 이 짜투리 부분은 mask를 통해 검정색으로 덮어씌운다
hue_shift = (hue + 40) % 180
#mask를 줘서 원 안에 있는 것들만 계산
#첫번째 인덱스가 평균값이다.
#mean_of_hue은 십원인지 백원인지 판정할수 있는 지표가 된다
#mask를 컬러 동전과 겹친다 -> 바탕이 검정색
mean_of_hue = cv2.mean(hue_shift, mask)[0]
# Hue 평균이 90보다 작으면 10원, 90보다 크면 100원으로 간주
won = 100
if mean_of_hue < 90:
won = 10
sum_of_money += won
#글의 위치는 crop 원안에서 (20,50) 위치, 대략 중심위치이다.
#글자 크기는 0.75, 두께 2
cv2.putText(crop, str(won), (20, 50), cv2.FONT_HERSHEY_SIMPLEX,
0.75, (255, 0, 0), 2, cv2.LINE_AA)
#전체 금액을 dst 상단에 보여준다
cv2.putText(dst, str(sum_of_money) + ' won', (40, 80),
cv2.FONT_HERSHEY_DUPLEX, 2, (255, 0, 0), 2, cv2.LINE_AA)
cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
728x90
'실습 note' 카테고리의 다른 글
OpenCV_7(영상분할&객체검출) (0) | 2021.02.25 |
---|---|
OpenCV_6(이진 영상 처리) (0) | 2021.02.24 |
OpenCV_4(기하학적 변환) (0) | 2021.02.22 |
버스 승차인원 예측 실습(데이콘 경진대회 1등 솔루션) (0) | 2021.02.20 |
KBO 타자 OPS 예측 실습(데이콘 경진대회 1등 솔루션) (0) | 2021.02.20 |