본문 바로가기
Python/openCV

Python openCV 기본

by code2772 2023. 3. 8.

[ 목차 ]

    728x90
    반응형
    영상(image)
    픽셀(pixel) : 바둑판 모양의 격자에 나열괴어 있는 형태, 2차원 행렬
    
    1. 그레이스케일 영상
        - 흑백사진처럼 색상 정보가 없는 영상
        - 밝기 정보만으로 구성된 영상
        - 밝기 정보는 256단계로 표현(0 ~ 255)
        - numpy.uint8 = 8bit = 1byte
        - 가로크기 * 세로크기 = 28 * 28 = 784 bytes
    
    2. 트루컬러 영상
        - 컬러사진처럼 색상 정보를 가지고 있기 때문에 다양한 색상을 표현할 수 있는 영상
        - red, green, blue 색 성분을 사용하고, 각 256단계로 표현
        - 픽셀의 표현 -> (255, 255, 255)
        - 튜플, numpy.ndarray = 3byte
        - 가로크기 * 세로크기 * 3 = 28 * 28 * 3 = 2352 bytes
    
    영상 파일 형식
    1. bmp
        - 픽셀 데이터를 압축하지 않고 그대로 저장
        - 용량이 매우 큼
        - 파일 구조가 단순해서 별도의 라이브러리 없이 프로그래밍이 가능
    2. jpg, jpeg
        - 압축률이 좋아서 파일 용량이 크게 감소
        - 사진과 같은 컬러영상을 저장
        - 손실 압축(복사 붙여넣기 하는 경우 특정 이미지의 알고리즘으로 실제 값들이 손실된다)
    3. gif
        - 움직이는 영상 지원(움짤)
        - 256색 이하의 영상을 저장
        - 무손실 압축
    4. png
        - 무손실, 손실 압축
        - 알파 채널(투명도)을 지원 -> Ex)사진 합성
    
    OpenCV 라이브러리 : 실시간 이미지 프로세싱에 중점을 둔 라이브러리이다
    - 1999년 인텔이 주도적으로 개발시작(이후 오픈소스로 개발)
    - 영상처리에 관련된 라이브러리
    - C로 구현 : 함수&구조체 -> v1
    - 2011년 이후 opencv2 -> v2 ~
    https://docs.opencv.org/4.x/   -  opencv 소개 주소
    
    
    pip install opencv-python  : opencv 설치

    ✔ opencv 기본

    import cv2 # opencv2 사용하기 위해 임포트
    
    print('현재 opencv 버전: ', cv2.__version__)
    
    # 이미지 불러오기 , 영상처리
    img = cv2.imread('cat.bmp') #  영상 불러오기
    cv2.imshow('img', img) # 영상 보여주기
    cv2.waitKey() # 지워 지지 않고 해당 키를 누를 때까지 하기
    예제 1번 결과
    matplotlib 설치
    pip install matplotlib
    
    그레이스케일 영상 출력
    1. plt.imshow() 함수에서 컬러맵(cmap)을 gray로 설정
    2. opencv에서 영상을 부를 때 cv2.IMREAD_GRAYSCALE을 사용
    
    컬러 영상 출력하기
    1. 컬러 영상의 새강정보는 RGB 순서
    2. cv2.imread() 메소드로 불러온 영상의 색상 정보는 BGR 순서이기 때문에 matplotlib에서 출력하려면
        RGB 순서로 cv2.cvtColor() 메소드를 사용하여 변경해야 함

    ✔ matplotlib 예제

    import cv2
    import matplotlib.pyplot as plt
    
    # img_gray = cv2.imread('cat.bmp') 컬러
    # img_gray = cv2.imread('cat.bmp', cv2.IMREAD_COLOR) 컬러
    img_gray = cv2.imread('cat.bmp', cv2.IMREAD_GRAYSCALE)
    # plt.axis('off') # matplotlip을 사용 축 없에기
    # plt.imshow(img_gray, cmap='gray')
    # plt.show()
    
    img_rgb = cv2.imread('cat.bmp') # 이미지 정보가 블루, 그린, 레드 순으로 읽어온다
    img_rgb = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2RGB) # COLOR_BGR2RGB : BGR -> RGB로 변경하는 속성
    # plt.axis('off') # matplotlip을 사용 축 없에기
    # plt.imshow(img_rgb)
    # plt.show()
    
    # subplot 만들기
    # 컬러 + 흑백
    plt.subplot(121) # 1행 2열의 첫번째
    plt.axis('off')
    plt.imshow(img_rgb)
    
    plt.subplot(122) #  1행 2열 2번째
    plt.axis('off')
    plt.imshow(img_gray, cmap='gray')
    plt.show()
    예제2 결과
    영상의 속성과 픽셀값
    OpenCV는 영상 데이터를 numpy.ndarray로 표현
    
        img = cv2.imread('cat.bmp', cv2.IMERAD_GRAYSCALE)
        --------
        numpy.ndarray
    
        img.shape : 각 차원의 크디. 그레이스케일은 (h, w)이며 컬러영상은 (h, w, 3)
        img.size : 전체 원소의 개수
        img.dtype : 원소의 데이터 타입. 영상 데이터 uint8
    
    지정한 크기로 영상 생성하기
    numpy.empty() : 임의의 값으로 초기화된 배열을 생성
    numpy.zeros() : 0으로 초기화된 배열을 생성
    numpy.ones() : 1로 초기화된 배열을 생성
    numpy.full() : 원하는 값으로 초기화된 배열을 생성
    

    ✔ ndarray 예제

    import cv2
    
    img1 = cv2.imread('cat.bmp', cv2.IMREAD_GRAYSCALE)
    print('img1의 type: ', type(img1)) # 이미지가 ndarray로 저장된다. ndarray로 저장되기 때문에 shape는 존재한다
    print('img1의 shape: ', img1.shape) # (480, 640) = (세로, 가로)
    print('img1의 dtype: ', img1.dtype) # uint8, 밝기 정보
    
    img2 = cv2.imread('cat.bmp')
    print('img2의 type: ', type(img2))
    print('img2의 shape: ', img2.shape) # (480, 640, 3) -> (세로, 가로, 컬러)
    print('img2의 dtype: ', img2.dtype)
    
    h, w = img2.shape[:2]
    print(f'img2의 사이즈 : {w} * {h}')
    
    # 흑백과 컬러 영상을 구별하는 방법
    if len(img1.shape) == 2:
        print('img1은 흑백입니다.')
    elif len(img1.shape) == 3:
        print('img1은 컬러입니다.')
    
    # 특정 밝기 정보와 특정 색정보로 영상 출력하기
    # for x in range(h):
    #     for y in range(w):
    #         img1[x, y] = 255
    #         img2[x, y] = (255, 102 , 255) # BGR
    
    img1[:,:]= 255 # 이중 포문을 사용하는 것보다 속도가 훨씬 빠르다
    img2[:,:]= (255, 102, 255)
    
    cv2.imshow('img1', img1)
    cv2.imshow('img2', img2)
    cv2.waitKey()
    예제3 결과

    ✔ 이미지 만들기

    import cv2
    import numpy as np
    # numpy : empty
    
    img1 = np.empty((240, 320), dtype=np.uint8)
    img2 = np.zeros((240, 320, 3), dtype=np.uint8)
    img3 = np.ones((240, 320), dtype=np.uint8) * 150
    img4 = np.full((240, 320, 3), (255, 102, 255), dtype=np.uint8)  # 채우고 싶은 부분
    #                   3채널을      이걸로 다 채워라
    
    cv2.imshow('img1', img1)
    cv2.imshow('img2', img2)
    cv2.imshow('img3', img3)
    cv2.imshow('img4', img4)
    cv2.waitKey()
    예제 4 결과

    ✔ 이미지 복사

    import cv2
    
    # 원본 이미지
    img1 = cv2.imread('cat.bmp')
    # 원본을 동일하게 가리키는 주소
    # img2 = img1
    
    
    img_re = cv2.resize(img1, (500,500))
    # 원본과 동일한 주서의 이미지 일부
    img2 = img_re[64:300, 165:450]
    # 복사본의 일부
    img3 = img1[64:300, 165:450].copy()
    # img2.fill(0)
    img3.fill(0)
    
    cv2.imshow('img_re', img_re)
    cv2.imshow('img2', img2)
    cv2.imshow('img3', img3)
    
    cv2.waitKey()
    예제5 결과

    ✔ 이미지 그리기

    import cv2
    import numpy as np
    
    img = np.full((500, 500, 3), 255, np.uint8)
    
    # 선 만들기
    cv2.line(img, (50,50), (200,50), (0, 0, 255), 5)
    cv2.rectangle(img, (50, 200, 150 , 100), (0, 255, 0), -1)
    cv2.circle(img, (300,  100),50, (255, 255, 0), -1)
    
    str = 'HEllo OpenCV'
    cv2.putText(img, str, (50,35), cv2.FONT_HERSHEY_DUPLEX, 0.8, (0,0,255))
    
    
    cv2.imshow('img', img)
    cv2.waitKey()
    이미지 그리기 결과
    직선 그리기
    cv2.line(영상, 직선의 시작점과 끝점, 선색상, 선두께, 선타입)
    
    사각형 그리기
    cv2.rectangle(영상, 사각형 꼭지점 좌표, 선색상, 선두께)
    * 선두께가 -1 으로 설정하면 사각형 내부를 색상으로 채움
    
    원 그리기
    cv2.circle(영상, 원의 중앙좌표, 반지름, 선색상, 선두께)
    
    문자열 출력하기
    cv2.putText(영상, 문자열, 영상에서 문자열을 출력할 위치의 좌표, 글꼴, 폰트크기)
    
    * 글꼴
    FONT_HERSHEY_SIMPLEX
    FONT_HERSHEY_PLAIN
    FONT_HERSHEY_DUPLEX
    FONT_HERSHEY_COMPLEX
    FONT_HERSHEY_TRIPLEX
    FONT_HERSHEY_COMPLEX_SMALL

    ✔ 캠 연결하기

    import cv2
    import sys
    
    cap = cv2.VideoCapture(0) # 동영상 파일, 캠 을 다룰 수 있다.
    
    if not cap.isOpened():
        print('카메라를 열 수 없습니다')
        sys.exit() # 더 이상 프로그램을 진행시키지 않기 위해 ,아에 종료
    
    print('카메라 연결 성공!')
    print('가로 사이즈 : ', int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)))
    print('세로 사이즈 : ', int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
    
    while True:
        ret, frame = cap.read()
        if not ret:
            break
    
        inversed = ~frame
    
        cv2.imshow('frame', frame)
        cv2.imshow('inversed', inversed)
    
        if cv2.waitKey(10) == 27: # ESC
            # 키를 받으려고 대기중에 있는데 27번 esc를 누르면 종료가 된다
            break

    ✔ 영상 처리 설명

    동영상 처리하기
    cv2.VideoCapture 클래스
    - 카메라와 동영상으로부터 프레임(frame)을 받아오는 작업을 처리함
    
    카메라 영상
    cv2.VideoCapture(index)
    index: 시스템의 기본 카메라를 open 하려면 0또는 숫자를 사용
    
    cv2.VideoCapture.isOpened()
    True : 성공
    False : 실패
    
    cv2.CAP_PROP_FRAME_WIDTH : 카메라로 읽어들인 영상의 가로 사이즈
    cv2.CAP_PROP_FRAME_HEIGHT : 카메라로 읽어들인 영상의 세로 사이즈
    
    cv2.VideoCapture.read()
    영상의 프레임과 프레임이 제대로 리턴되었는지 여부
    ret : 영상이 정상적으로 리턴되었는지 여부 (True, False)
    frame : 영상
    반응형