본문 바로가기
개발/OpenCV

2023.07.24 OpenCV란?

by 상달군 2023. 8. 10.
728x90

목차. 

 

1. OpenCV (Open Source Computer Vision Library)

2. 컴퓨터 비전 (Computer Vision)

3. 영상(Image)평가 진행 과정

4. 도형 그리기

5. 동영상 처리하기 

Q1. 문제코드 (두 동영상을 연결하는 프로그램 만들기)

Q2. 과제코드 (두 동영상이 지나가듯 연결 하는 프로그램)


1. OpenCV(Open Source Computer Vision Library)

 - 컴퓨터 비전과 이미지 처리를 위한 오픈소스 라이브러리 입니다.
 - 1999년 Intel에서 영상처리 기술을 개발하기 위한 목적으로 만들어졌다.
 - 2000년 BSD 라이센스로 배포 하였다. (사이킷런도 BSD 라이센스로 배포)
 - 2011년 이후 OpenCV2로 개발 시작 (지금 버전은 OpenCV4이지만 아직까지고 그냥 OpenCV2라고 불리고 있다. )

 - 설치 (파이썬에 존재하는 CV2라는 라이브러리랑은 다른거임 !!! )

pip install opencv-python

2. 컴퓨터 비전(Computer Vision)

 - 컴퓨터를 사용하여 디지털 이미지나 비디오에서 정보를 추출하고, 해석하는 기술과 분야
 - 이미지 처리, 객체탐지, 패턴인식, 광학문자인식(OCR) ....


3. 영상(image)

 📌 동영상과는 다르다. 영상 이미지라고 부르고 움직이는 이미지동영상이라한다.!


📌 픽셀(pixel)

    - 이미지를 구성하는 가장 작은 단위
    - 바둑판 모양의 격자에 나열되어 있는 형태, 2차원 배열이다.


📌 그레이스케일 영상

    - 흑백사진처럼 색상 정보가 없는 영상을 "그레이스케일 영상"이라 한다.

        (흑백사진"처럼!!" 이지 흑백사진이랑은 다르다!)
    - 밝기 정보만으로 구성된 영상
    - 밝기 정보는 256단계로 표현(0~255) [numpy.uint8]
    - numpy.uint8 = 8bit = 1byte (u가 붙어 있으면 언사이드int8이기 때문에 "부호비트를 사용하지 않겠다"라는 뜻으로 +의 값 0~255까지 사용가능하다!)
    - 용량계산 : 가로크기 * 세로크기 = 28 * 28 = 784byte

 

📌 트루컬러 영상

    - 컬러사진처럼 색상 정보를 가지고 있기 때문에 다양한 색상을 표현할 수 있는 영상
    - RED, GREEN, BLUE 색 성분을 사용하여, 각 256단계로 표현한다.
    - 픽셀의 표현 -> 튜플 형태로 표현 한다. -> (255, 255, 255)
    - numpy.ndarray = 3byte
    - 용량계산 : 가로크기 * 세로크기 *3 = 28 * 28 *3= 2352byte


 📌 영상 파일 형식

    - bmp
        * 픽셀 데이터를 압축하지 않고 그대로 저장한다.
        * 용량이 매우 큼( 픽셀의 일반적인 용량)
        * 파일 구조가 단순해서 별도의 라이브러리 없이 프로그래밍이 가능하다.


    - jpg, jpeg
        * 압축률이 좋아서 파일 용량이 크게 감소 한다.
        * 사진과 같은 컬러 영상을 저장 한다.
        * 손실 압축 ( 조금씩 짤라서 압축한다. 그래서 복사를 계속하면 사진이 뿌옇게 변함)


    - gif
        * 움직이는 영상 지원
        * 256색 이하의 영상을 저장한다.
        * 무손실 압축형식


    - png
        * 웹 이미지용으로 권장한다.
        * 무손실, 손실 압축 을 모두 지원한다.
        * 알파 채널(투명도)을 지원한다. (255, 255, 255, 1)


 📌 영상 출력

    - 그레이스케일 영상 출력
        * cv2.IMREAD.GRAYSCALE을 사용한다.
        * img.shape: 차원의 크기를 말하는데, (h(세로), w(가로)


    - 컬러 영상 출력
        * cv2.imread() : 메소드로 불러온 영상의 색상 정보는 BGR 순서로 불러온다.
        * matplotlib에서 출력하려면 RGB순서로 변경해주어야 하기 때문에 cv2.cvtColor()메소드를 사용하여 변경 해야함
        * img.shape: 차원의 크기를 말하는데, ((h(세로), w(가로), 3)


4. 도형 그리기

📌직선 그리기
    cv2.line(영상, 직선의 시작점과 끝점(튜플로 저장), 선 색상, 선 두께, 선 타입)
📌사각형 그리기
    cv2.rectangle(영상, 사각형의 꼭지점 좌표(튜플로 저장), 선 색상, 선 두께) // 선 두께가 '-1'인 경우, 사각형 내부를 색상으로 채움
📌원 그리기
    cv2.circle(영상, 원의 중앙 좌표(튜플로 저장), 반지름, 선 색상, 선 두께// 선 두께가 '-1'인 경우, 원 내부를 색상으로 채움
📌문자열 출력하기
    cv2.putText(영상, 문자열, 영상에서 문자열을 출력할 위치 좌표, 글꼴, 폰트 크기)


4. 동영상 처리하기

 📌 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: 영상(그레이스케일 영상 또는 컬러영상)


 📌 동영상 입력

    - 카메라 영상 불러오는것과 다 똑같고 '파일명'만 넣어주면 된다.
        cv2.VideoCapture(파일명)

 

 📌 동영상 출력

    - FourCC(Four Character Code)
        * 4바이트로 된 문자열이며, 데이터 형식을 구분하는 고유 글자
        * 주로 AVI 파일의 영상 코덱을 구분할 때 사용한다.
        * Divx, Xvid, H264 ... (동영상을 압축하는 형식종류 )
            cv2.VideoWriter_fourcc(*'DIVX')
            cv2.VideoWriter_fourcc(*'Xvid')
            cv2.VideoWriter_fourcc(*'MP4V')
            ....


    - 파일 저장 방법
        cv2.VideoWriter(파일명, FourCC객체, fps, 프레임 사이즈, 컬러영상여부)
            * 프레임사이즈: (W, H) 튜플형식으로 입력
            * 컬러 영상 여부: 컬러면 True, 그레이스케일이면 False


Q1. 문제 코드

무료 동영상 사이트에서 동영상 2개를 다운받아 두 동영상을 연결하는 프로그램 만들기
- 단, 두 영상의 해상도가 같아야 함

import sys
import numpy as np
import cv2

cap1 = cv2.VideoCapture('./aa.mp4')
cap2 = cv2.VideoCapture('./bb.mp4')

if not cap1.isOpened() or not cap2.isOpened():
    print('동영상 연결 실패')
    sys.exit()


frame_cnt1 = round(cap1.get(cv2.CAP_PROP_FRAME_COUNT))
frame_cnt2 = round(cap2.get(cv2.CAP_PROP_FRAME_COUNT))
fps = cap1.get(cv2.CAP_PROP_FPS)
effect_frames = int(fps * 2)

print('frame_cnt1:', frame_cnt1)
print('frame_cnt2:', frame_cnt2)
print('FPS:', fps)

delay = int(1000 / fps)

w = round(cap1.get(cv2.CAP_PROP_FRAME_WIDTH))
h = round(cap1.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'DIVX')

# 출력 동영상 객체 생성
out = cv2.VideoWriter('output.avi', fourcc, fps, (w, h))

# aa.mp4 동영상
for i in range(frame_cnt1 - effect_frames):
    ret1, frame1 = cap1.read()

    if not ret1:
        break

    out.write(frame1)
    cv2.imshow('frame', frame1)
    cv2.waitKey(delay)

# 합성 과정
for i in range(effect_frames):
    ret1, frame1 = cap1.read()
    ret2, frame2 = cap2.read()

    if not ret1 or not ret2:
        print('frame read error!')
        sys.exit()

    dx = int(w / effect_frames * i)
    frame_new = np.zeros((h, w, 3), dtype=np.uint8)

    frame_new[:, 0:dx, :] = frame2[:, 0:dx, :]
    frame_new[:, dx:w, :] = frame1[:, dx:w, :]

    out.write(frame_new)
    cv2.imshow('frame', frame_new)
    cv2.waitKey(delay)

# bb.mp4 동영상
for i in range(effect_frames, frame_cnt2):
    ret2, frame2 = cap2.read()

    if not ret2:
        break

    out.write(frame2)
    cv2.imshow('frame', frame2)
    cv2.waitKey(delay)

cap1.release()
cap2.release()
out.release()

 

mix.avi
10.67MB


Q2. 과제 코드

위 문제에서 1번 동영상 끝나기 2초전 부터 2번 동영상이 좌측에서 시작되어
2초가 끝나면 2번 동영상이 모두 보이는 형태의 프로그램 만들어보자
 -  슬라이드처럼  좌측에서 밀고나오기

import cv2
import numpy as np


# 이미지 불러오기
image = cv2.imread("namecard.jpg")
# ROI를 선택하고자 하는 이미지 복사해서 재표시
clone_image = image.copy()
cv2.imshow("Select ROI", image)

# 사다리꼴을 그리기 위한 점의 좌표를 리스트로 정의
points = []

def on_mouse(event, x, y, flags, param):
    global points
    if event == cv2.EVENT_LBUTTONDOWN:
        points.append((x, y))
        cv2.circle(clone_image, (x, y), 5, (0, 255, 0), -1)
        cv2.imshow("Select ROI", clone_image)

        # 4개의 점을 선택하면 사다리꼴 그리기
        if len(points) == 4:
            points_arr = np.array(points, np.int32)
            cv2.polylines(clone_image, [points_arr], isClosed=True, color=(0, 255, 0), thickness=2)
            cv2.imshow("Select ROI", clone_image)

            # 선택한 사다리꼴 내부를 마스킹하여 ROI 추출
            roi_mask = np.zeros(image.shape[:2], dtype=np.uint8)
            cv2.fillPoly(roi_mask, [points_arr], (255, 255, 255))
            roi = cv2.bitwise_and(image, image, mask=roi_mask)

            w, h = 550, 300
            dstQuad = np.array([[0,0], [w,0], [w,h], [0,h]], np.float32)
            srcQuad = np.array([[21, 445], [510, 211], [722, 405],[214, 748]], np.float32)

            if cv2.waitKey() == 13:
                pers = cv2.getPerspectiveTransform(srcQuad, dstQuad)
                dst = cv2.warpPerspective(roi, pers, (w, h))
                cv2.imshow('dst', dst)
                cv2.waitKey()


# 마우스 이벤트 콜백 함수 등록
cv2.setMouseCallback("Select ROI", on_mouse)
cv2.waitKey()

output.avi
10.15MB

728x90

'개발 > OpenCV' 카테고리의 다른 글

2023.07.24 OpenCV Day1(4.Createimg ~ 6.Drawing)  (0) 2023.08.21
2023.07.24 OpenCV Day1(OpenCV~Imageinfo)  (0) 2023.08.21

댓글