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

+ Recent posts