충돌 방지를 위해 jupyter 3.7버전으로 anaconda에서 만들어서 실행
# 파이썬 버전 확인
import sys
print(sys.version)
3.7.13 (default, Mar 28 2022, 08:03:21) [MSC v.1916 64 bit (AMD64)]
OpenCV 개요
- Computer Vision : 사람의 시작적인 부분을 기계로 구현하는것을 목적으로 하는 딥러닝 분야
- 이미지, 동영상 등의 처리를 지원하는 라이브러리
- C++로 제작되어 있고 Java, Android, Python 등 다양한 언어에서 구현 가능
- 특히 Python에서 OpenCV를 사용할 경우 Numpy, Matplotlib 등의 라이브러리들과 바로 연동 가능
유용한 OpenCV 사이트
- https://opencv.org/ : OpenCV 공식 사이트
- https://blog.naver.com/samsjang/220498694383 : 잘 정리된 OpenCV 관련 블로그 (코드 복사 가능)
- https://m.blog.naver.com/samsjang/220498694383 : 위의 블로그와 동일한 블로그 (내용 추가)
- https://github.com/opencv/opencv : OpenCV github 사이트
- https://learnopencv.com/ : 높은 수준의 결과물을 낼 수 있는 다양한 코드 제공 (프로젝트에 활용)
- https://github.com/spmallick/learnopencv/blob/master/README.md?ck_subscriber_id=1390420859 : 파이토치로 된 좋은 예시 코드
- https://github.com/LongxingTan/Yolov5 : YoloV5
import numpy as np
import matplotlib.pyplot as plt
# OpenCV 임포트
import cv2
# 이미지 불러오기
cat = cv2.imread('image/image_cat.jpg')
# OpenCV와 matplotlib간 연동됨
plt.imshow(cat);

OpenCV의 색상 체계
- 일반적인 이미지는 RGB 색상을 사용
- OpenCV에서는 BGR색상 체계를 사용함(그래서 RGB를 그대로 사용하면 Red계열 색상이 Blue계열로 변경되어 출력됨)
- 초기에는 알파벳 순서대로 BGR로 쓰다가 이후에 색상 주파수가 낮은 순으로 RGB로 바뀌어 현재는 RGB가 대중적으로 사용됨
- OpenCV에서는 RGB를 BGR로 변환하여 불러와야 함
cat = cv2.imread('image/image_cat.jpg')
# cvtColor : 색상 변환 함수
cat2 = cv2.cvtColor(cat, cv2.COLOR_RGB2BGR)
# x축, y축 좌표 눈금을 없애고 싶을때
plt.xticks([])
plt.yticks([])
plt.imshow(cat2)


이미지 색상 변환
- 컬러 이미지(RGB)
- 흑백 이미지(Gray) -> 0~255 사이의 흑백 픽셀값으로 구성된 이미지
- 컬러 이미지는 용량이 크고 연산량이 많기 때문에 실시간 처리가 힘들고, 이를 간소화시켜 계산과 연산을 용이하게 하기 위해 흑백이미지나 이진이미지를 사용
- 컬러 이미지는 채도와 명도에 영향을 받기 때문에 이를 최소화 하기 위함
- 명도(밝은 정도) - 밤에 색상을 볼 때 정확한 색상을 보여주지 못하는 경우 존재
- 채도(탁한 정도) - 색상에 빛을 강하게 비추는 경우 정확한 색상을 보지 못하는 경우가 존재
- 이진 이미지(binary) -> 0(검정)과 255(흰) 두가지 색상으로만 구성된 이미지
- 배경과 객체를 구분
- 관심 영역과 비관심 영역을 분리
- 필터를 만들거나 단순한 이미지 처리를 할 경우 사용
흑백(Gray) 이미지 만드는 방법
1. 기존 컬러 이미지를 Gray로 불러서 출력하기
# 이미지를 불러올때 gray로 받아주고 출력시에도 gray 색상으로 변환하여 출력
cat_gray = cv2.imread("image/image_cat.jpg", cv2.IMREAD_GRAYSCALE)
plt.imshow(cat_gray, cmap='gray')

2. 컬러 이미지를 그대로 불러온 다음 cvColor를 통해 gray로 변환 후 출력하기
cat2 = cv2.imread("image/image_cat.jpg")
cat2_gray = cv2.cvtColor(cat2, cv2.COLOR_BGR2GRAY)
plt.imshow(cat2_gray, cmap='gray');

이진(binary) 이미지 만들기
- 기존 이미지가 컬러 이미지라면 gray로 변환 후에 이진 이미지로 만들어줘야함
# threshold : 특정 기준을 통해서 데이터를 변환시켜주는 함수(문턱(경계)이라는 뜻)
# (이미지, 경계 기준값, 경계값보다 클 경우 적용되는 값, 경계값 적용 방식)
# 경계 기준값 : 0 ~ 255 값 중에서 선택
# 적용값 : 기준값보다 큰 경우에 할당되는 값(150보다 크면 255, 작으면 0)
_, bi_cat = cv2.threshold(cat2_gray, 128, 255, cv2.THRESH_BINARY)
# _ : 첫번째 리턴값은 받지 않음(경계값 / 위에선 128)
# bi_cat : 두번째 리턴값은 threshold가 적용된 이미지 데이터
plt.imshow(bi_cat, cmap='gray')

temp, bi_cat = cv2.threshold(cat2_gray, 128, 255, cv2.THRESH_BINARY)
temp
128.0
bi_cat
array([[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
...,
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0]], dtype=uint8)
경계값 적용 방식 종류
- cv2.THRESH_BINARY : 픽셀값이 경계값보다 크면 value(적용값), 아니면 0을 할당(흭색, 검은색으로만 표시)
- cv2.THRESH_BINARY_INV : THRESH_BINARY의 반대(픽셀값이 경계값보다 크면 0, 아니면 value를 할당)
- cv2.THRESH_TRUNC : 픽셀값이 경계값보다 크면 경계값, 아니면 픽셀값을 그대로 할당
- cv2.THRESH_TOZERO : 픽셀값이 경계값보다 크면 픽셀값, 아니면 0을 할당 (0은 검은색으로 검은색을 좀 더 부각)
- cv2.THRESH_TOZERO_INV : THRESH_TOZERO의 반대(픽셀값이 경계값보다 크면 0, 아니면 픽셀값 할당)

동영상 혹은 카메라(웹 캠) 불러오기
- 카메라로부터 프레임 캡쳐 후 연결하여 영상으로 보여주기
- 동영상 파일로부터 프레임 캡쳐 후 연결하여 영상으로 보여주기
# 영상 파일을 다룰 때는 예외처리(제대로 동작하지 않았을 경우에 대한 처리)를 해주는
# 것이 오류 방지에 좋다
# 1. 영상 파일에서 프레임단위로 사진을 캡쳐해 받아오기
try:
# VideoCapture : 동영상을 프레임 단위로 캡쳐
cap = cv2.VideoCapture("image/video.mp4")
print("비디오 캡쳐 시작")
except:
print("비디오 캡쳐 실패")
# 2. 캡쳐해 온 프레임 출력
ret, frame = cap.read()
print(ret)
print(frame)
plt.imshow(frame)
비디오 캡쳐 시작
True
[[[177 152 90]
[175 151 89]
.................
[[ 48 46 19]
...
[ 42 31 17]]
[[ 31 29 2]
...
[ 27 16 2]]]

# 영상 파일을 다룰 때는 예외처리(제대로 동작하지 않았을 경우에 대한 처리)를 해주는
# 것이 오류 방지에 좋다
# 1. 영상 파일에서 프레임단위로 사진을 캡쳐해 받아오기
try:
# VideoCapture : 동영상을 프레임 단위로 캡쳐
# 1) 웹캠으로 부터 캡쳐
# 카메라번호 - USB포트 번호, 일반적으로 웹캠 하나 : 0번
# cap = cv2.VideoCapture(0)
# 2) 동영상으로 부터 캡쳐
cap = cv2.VideoCapture("image/video.mp4")
print("비디오 캡쳐 시작")
except:
print("비디오 캡쳐 실패")
# 2. 캡쳐해 온 프레임 계속해서 한 장씩 읽어와 연결하여 출력(영상으로 보여준다)
while True:
# read : 캡쳐한 이미지 프레임을 한 장씩 읽어오는 함수
# ret : 읽기 성공여부(True, False)
# frame : 읽어온 이미지 데이터(numpy 배열 타입)
ret, frame = cap.read()
# 프레임을 읽지 못했거나 영상의 모든 프레임을 다 읽었을 경우 종료
if ret==False :
print("프레임 읽기 실패 or 프레임 모두 읽음")
# 비디오 캡쳐 종료
cap.release()
# 생성한 창을 모두 닫아주기
cv2.destroyAllWindows()
break
#윈도우 창 크기 변경
frame = cv2.resize(frame,(1000,700))
# 흑백 영상 출력
frame = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
#imshow(OpenCV):새 윈도우 창을 띄워서 이미지를 계속 출력(윈도우창 이름, 전달받을 프레임)
cv2.imshow("Video", frame)
# waitKey : 키보드에 특정 키 값을 입력할 때까지 기다리는 명령
# (숫자) : 한 장의 프레임을 읽어들이고 40ms(0.004초) 기다렸다가 다음 사진을 읽어들일
# 수 있도록 딜레이를 주는 역할
key = cv2.waitKey(40)
# ex) 영상이 초당 60 프레임이라면 1000/60 -> 16.66 16ms로 설정해야 한다
# 영상 초당 프레임수와 waitKey값의 차이가 나면 플레이 자체는 문제 없지만
# 마지막 프레임이 잘리는 현상이 발생할 수 있음
# 재생중에 영상을 끄고 싶을 경우
# 윈도우 창의 X를 누르지 말고 키보드로 멈춰야한다(X누르면 에러or커널 재시작해야함)
# 27 : 아스키코드로 ESC , 49는 아스키코드로 1
if key == 27 :
print("동영상 읽기 종료")
cap.release()
cv2.destroyAllWindows()
break
영상 녹화하기
try:
cap = cv2.VideoCapture("image/video.mp4")
print("비디오 캡쳐 시작")
except:
print("비디오 캡쳐 실패")
# 녹화될 파일 설정
fps = 30.0 # 초당 프레임 수
w = int(cap.get(3)) # 캡쳐한 비디오의 가로(3)크기
h = int(cap.get(4)) # 캡쳐한 비디오의 세로(4)크기
# 영상의 코덱 설정(CODEC : COder and DECoder)
# COder : 음성 또는 영상의 신호를 디지털 신호로 변환
# DECoder : corder의 반대
# DIVX : 일반적으로 avi 파일에 많이 사용되는 코덱
codec = cv2.VideoWriter_fourcc(*'DIVX')
out = cv2.VideoWriter("image/record_file.avi", codec, fps, (w,h))
# 녹화 상태 여부
record = False
while True:
ret, frame = cap.read()
if ret == False:
print("비디오 읽기 실패 또는 비디오 모두 읽음")
cap.release()
out.release()
cv2.destroyAllWindows()
break
cv2.imshow("record", frame)
# 영상 녹화 시작 여부
if record: # record가 True가 되면 녹회 시작
out.write(frame)
k = cv2.waitKey(40)
if k == 27 :
print("영상 및 녹화를 종료합니다")
cap.release()
out.release()
cv2.destroyAllWindows()
break
# 키보드 숫자2 : 50
if k == 50 :
record=True
print("녹화를 시작합니다")
이미지의 픽셀값 변경하기
img11 = cv2.imread("image/11.png")
img11 = cv2.cvtColor(img11, cv2.COLOR_BGR2RGB)
print("불러온 이미지 타입 : ",type(img11))
print(img11[150,330]) # 픽셀값에 접근([세로, 가로])
# 픽셀값 변경하기
for i in range(21):
for j in range(20):
img11[150+i,330+j] = [255,0,0]
plt.imshow(img11)
불러온 이미지 타입 : <class 'numpy.ndarray'>
[254 242 0]
<matplotlib.image.AxesImage at 0x21f3b695788>

ROI(Region of Interest)관심영역 추출하기
img11 = cv2.imread("image/11.png")
img11 = cv2.cvtColor(img11, cv2.COLOR_BGR2RGB)
roi_img11 = img11[160:220,280:390]
plt.imshow(roi_img11)

ROI 영역을 표시하고 글씨도 출력해보자
- rectangle : 사각형 그리는 함수
- circle : 원 그리는 함수
- purText : 글씨 출력 함수
img11 = cv2.imread("image/11.png")
img11 = cv2.cvtColor(img11, cv2.COLOR_BGR2RGB)
# 픽셀값은 배열구조라 ([세로,가로]) 이미지 접근은 (가로, 세로)
# 사각형 박스 출력(이미지명, 좌상단좌표, 우하단좌표, 색상, 선두께)
img11 = cv2.rectangle(img11, (280,160), (400,250), (255,0,0), 3)
# 텍스트 출력(이미지, 출력글씨, 출력좌표(좌측하단), 폰트, 폰트크기, 색상, 선두께)
img11 = cv2.putText(img11, "mouth", (300,150), cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,
1, (255,0,0), 2)
# 원형 출력(이미지, 원 중심좌표, 반지름(라디안), 색상, 선두께)
img11 = cv2.circle(img11, (75,165),(70),(255,0,0), 3 )
plt.imshow(img11)

OCR(Optical Character Recognition) - 광학문자판독
- 이미지에서 문자를 추출하는 라이브러리(Tesseract)
- https://ddolcat.tistory.com/954
# 파이썬용 tesseract 설치
!pip install pytesseract
import pytesseract
# 설치한 폴더의 위치를 설정
# \ : 밑에 이어서 한줄로 코드를 작성하는 것과 같은 효과
pytesseract.pytesseract.tesseract_cmd = \
"C:/Program Files/Tesseract-OCR/tesseract"
story = cv2.imread("image/story.png")
# lang : 언어 설정
result = pytesseract.image_to_string(story, lang="kor")
print(result)
소년
여기저기서 단풍잎 같은 슬픈 가을이 뚝뚝 떨어진다. 단풍잎
떨어져 나온 자리마다 봄을 마련해 놓고 나못가지 위에 하늘이
펼쳐 있다. 가만히 하늘을 들여다보려면 눈썸에 파란 물감이
든다. 두 손으로 따뜻한 볼을 쓸어 보면 손바닥에도 파란 물감
이 묻어난다. 다시 손바닥을 들여다본다. 손금에는 맑은 강물
이 흐르고, 맑은 강물이 흐르고, 강물 속에는 사랑처럼 슬픈 얼
굴ㅡ- 아름다운 순이의 얼굴이 어린다. 소년은 황홀히 눈을
감아 본다. 그래도 맑은 강물은 흘러 사랑처럼 슬픈 얼굴--
아름다운 순이의 얼굴은 어린다.
car = cv2.imread("image/car.png")
car = cv2.cvtColor(car,cv2.COLOR_RGB2BGR)
plt.imshow(car);

car = cv2.imread("image/car.png")
car = cv2.cvtColor(car,cv2.COLOR_RGB2BGR)
result = pytesseract.image_to_string(car, lang="kor")
print(result)
-> 결과가 없다
- 문자인식 전 이진이미지로 변경하면 판독 정확성이 올라감
car = cv2.imread("./image/car.png", cv2.IMREAD_GRAYSCALE)
_, bi_car = cv2.threshold(car, 128, 255, cv2.THRESH_BINARY)
plt.imshow(bi_car, cmap='gray');

car = cv2.imread("./image/car.png", cv2.IMREAD_GRAYSCALE)
_, bi_car = cv2.threshold(car, 128, 255, cv2.THRESH_BINARY)
result = pytesseract.image_to_string(bi_car, lang="kor")
print(result)
527 3108!
'빅데이터 서비스 교육 > 딥러닝' 카테고리의 다른 글
로이터 뉴스 카테고리 분류 실습(RNN, LSTM) (0) | 2022.07.27 |
---|---|
RNN모델 (0) | 2022.07.26 |
전이학습 & 데이터 확장 (0) | 2022.07.25 |
딥러닝 다중분류 모델 (3가지 동물 분류) - MLP, CNN, 데이터 확장 예제 (0) | 2022.07.22 |
CNN (0) | 2022.07.21 |