티스토리 뷰
OpenCv은 컴퓨터 비젼과 관련된 작업을 위한 강력하고 다양한 기능을 제공하는 Python의 이미지 전처리 라이브러리입니다. 주요 기능은 이미지의 기본적인 처리 작업(읽기 및 쓰기)과 필터링, 특징 추출 등의 복잡한 처리도 가능합니다. 또한 비디오 처리에 대한 작업도 가능하고, 카메라 스트림을 실시간으로 처리하고 객체 탐지 및 동작 인식 등을 수행할 수 있습니다. 이번 시간에는 기본적인 이미지 저장 및 스레시홀딩에 대해 알아보겠습니다.
#OpenCV 라이브러리 로드
import cv2
1. 이미지 실행 및 저장
jpg, jpeg, png 등과 같은 형식의 이미지를 읽기 위한 방식에는 여러가지가 존재합니다.
- IMREAD_COLOR : 이미지를 color로 읽고 투명한 부분은 무시하여 읽기
- IMREAD_GRAYSCALE : 이미지를 흑백으로 읽기
- IMREAD_UNCHANGED : 이미지를 color로 읽고 투명한 부분도 살리기
#이미지 실행&저장
img = cv2.imread('summer.png', cv2.IMREAD_UNCHANGED)
cv2.imshow('Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('result.png',img)
print('이미지 차원 : ', img.ndim)
print('이미지 크기 : ', img.shape)
print('이미지 전체 요소 개수 : ', img.size)
print('이미지 데이터 타입 : ', img.dtype)
print('이미지 각 요소의 바이트 크기 : ', img.itemsize)
#이미지 차원 : 3
#이미지 크기 : (552, 695, 3)
#이미지 전체 요소 개수 : 1150920(552*695*3)
#이미지 데이터 타입 : uint8
#이미지 각 요소의 바이트 크기 : 1
이미지를 읽은 후에는 사용자가 키보드의 아무 키나 누를때까지 대기하거나, 모든 윈도우를 닫는 기능을 추가할 수 있습니다.
2. 이미지 그리기
OpenCv에는 배경을 설정해 직접 이미지를 그릴 수 있는 기능이 존재합니다. 그린 이미지의 스타일(색, 두께) 등을 조정할 수 있습니다.
#이미지 그리기
img = np.full((500,500,3),255, dtype=np.uint8) #흰색 배경 그리기
img = cv2.line(img, (0,256),(256,0),(256,0,0),5) #선 시작좌표, 끝지점 좌표, 선 색깔, 선두께
img = cv2.rectangle(img, (150,150),(250,250),(256,256,0),3)
img = cv2.rectangle(img, (30,30),(80,80),(256,256,0),-1) #thickness을 -1로 설정하면 색을 칠할 수 있다
cv2.imshow('Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('result.png',img)

3. 관심 영역
이미지 내 원하는 영역을 따로 분리하여 특정 처리를 할 때 numpy나 함수를 이용하여 처리할 수 있습니다. 이미지에 특정 연산을 통해 정보를 획득할 때, 관심 영역에 대해서만 연산을 진행하면 연산 속도가 빨라지는 장점을 얻을 수 있습니다.
#Numpy을 이용한 관심영역 지정
img = cv2.imread('./dog.jpg')
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #BGR값을 RGB로 바꾸기
plt.imshow(rgb_img) #원본 이미지 출력
plt.show()
x,y=1000,1250
h=img.shape[1]
w=img.shape[0]
roi = rgb_img[y:y+1000, x:x+1800]
print(roi.shape)
plt.imshow(roi) #관심 영역만 추출하여 출력
plt.show()


#함수를 활용한 관심영역 지정
img = cv2.imread('./dog2.png')
x,y,w,h = cv2.selectROI('img',img) #화면에서 원하는 영역을 드래그로 지정
if w and h:
roi = img[y:y+h, x:x+w] #y부터 y+h까지, x부터 x+w까지 슬라이싱
cv2.imshow('cropped',roi)
cv2.moveWindow('cropped',0,0)
cv2.imwrite('./cropped2.jpg',roi)
cv2.waitKey()
cv2.destroyAllWindows()
roi = cv2.cvtColor(roi,cv2.COLOR_BGR2RGB)
plt.imshow(roi)
plt.show()
cv2에는 관심 영역을 지정하기 위한 함수로 selectROI을 사용합니다. 특별히 여러 ROI을 선택할 때는 selectROIs을 사용하여 관심 영역을 여러 번 지정할 수 있습니다.
4. 스레시홀딩(Thresholding)
스레시홀딩은 이미지의 픽셀 값을 어떤 임계점을 기준을 나누어 2가지 분류로 나누는 방법입니다. 이처럼 한 개의 픽셀 값을 2가지 값으로 표현할 수 있는 것을 '바이너리 이미지'라고 합니다. 이처럼 바이너리(이진화)를 하는 이유는 배경과 객체를 구분시키고, 관심 영역과 비관심 영역을 구분하기 위해서입니다. 픽셀 값의 분포를 확인해 이진 분리를 위한 임계점을 설정하는 것이 중요합니다.
첫 번째로 알아볼 스레시홀딩 방법은 '전역 스레시홀딩' 방법입니다. 픽셀 값이 특정 임계값을 넘으면 255, 넘지 않으면 0으로 지정해 이진 분리하는 방법입니다.
img = cv2.imread('./dog.jpg')
#모든 임계값 적용방법 비교
ret, thresh_cv1 = cv2.threshold(img,100, 230, cv2.THRESH_TOZERO)
ret, thresh_cv2 = cv2.threshold(img,100, 230, cv2.THRESH_BINARY)
ret, thresh_cv3 = cv2.threshold(img,100, 230, cv2.THRESH_BINARY_INV)
ret, thresh_cv4 = cv2.threshold(img,100, 230, cv2.THRESH_TRUNC)
ret, thresh_cv5 = cv2.threshold(img,100, 230, cv2.THRESH_TOZERO_INV)
images = {'original':img,
'tozero':thresh_cv1, 'binary':thresh_cv2,
'binary_inv':thresh_cv3, 'trunc':thresh_cv4,
'tozero_inv':thresh_cv5}
for i, (k,v) in enumerate(images.items()):
plt.figure(figsize=(12,8))
plt.subplot(3,2,i+1), plt.axis('off'), plt.imshow(v[:,:,::-1]),plt.title(k)
plt.show()
- THRESH_TOZERO : 픽셀값이 thresh값보다 크면 픽셀값을 적용, 아니면 0
- THRESH_BINARY : 픽셀값이 thresh값보다 크면 maxval 적용, 아니면 0
- THRESH_BINARY_INV : 픽셀값이 thresh값보다 크면 0 적용, 아니면 maxval
- THRESH_TRUNC : 픽셀값이 thresh값보다 크면 thresh적용, 아니면 픽셀값 그대로 적용
- THRESH_TOZERO_INF : 픽셀값이 thresh값보다 크면 0 적용, 아니면 픽셀값 그대로 적용
전역 스레시홀딩의 단점은 최적의 임계점을 찾지 못한다는 것입니다. '오츠 알고리즘'은 임계값을 자동으로 지정하여 최적의 이진 분리를 적용합니다. 최적 임계점을 찾는 방법은 모든 경우의 수 중에서 두 부류의 명암 분포가 가장 균일할 때의 임계점을 선택합니다. 이때, 히스토그램을 활용하면 용이한데, 히스토그램으로 사물 내 특정 명암값이 얼마나 많은지를, 사물과 배경의 명암값이 얼마나 다른지를 알 수 있습니다.
img = cv2.imread('./dog.jpg',cv2.IMREAD_COLOR)
img = img.copy()
if img is None:
print('image load failed')
bgr_planes = cv2.split(img)
colors = ['r','g','b']
fig = plt.figure(figsize=(10, 10))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img), plt.axis('off')
plt.show()
for (p,c) in zip(bgr_planes, colors):
hist = cv2.calcHist([p],[0],None,[256],[0,256]) #RGB값의 분포 확인
plt.plot(hist, color=c)

img = cv2.imread('./dog2.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh_cv = cv2.threshold(img,127,255,cv2.IMREAD_GRAYSCALE)
#오츠 알고리즘 적용
ret, otsu = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
print('최적의 임계점 : ', ret) #168.0
cv2.imshow('img',img)
cv2.imshow('thresh_cv',thresh_cv)
cv2.imshow('otsu',otsu)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.waitKey(1)
'적응형 스레시홀딩'은 이미지를 여러 영역으로 나눈 뒤, 주변 픽셀 값을 이용해 임계값을 설정합니다. 두 가지 방법으로 임계값을 설정할 수 있는데, 이웃 픽셀의 평균으로 임계값을 설정하면 선명도는 높지만 잡티가 존재합니다. 반대로, 가우시안 분포를 활용해 임계값을 설정하면 선명도는 낮아지지만 잡티는 존재하지 않습니다.
from keras.preprocessing import image
img = cv2.imread('./dog2.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blk_size=9 #영역으로 나눌 이웃의 크기
C=5 #계산된 임계값 결과에서 가감할 수
#적응형 스레시홀딩을 평균과 가우시안분포로 각각 적용
th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C, #이웃 픽셀의 평균으로 결정
cv2.THRESH_BINARY, blk_size,C)
th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, #가우시안 분포에 따른 가중치의 합으로 결정
cv2.THRESH_BINARY, blk_size,C)
imgs = {'Original':img, 'adaptive-mean':th2, 'adaptive-gaussian':th3}
for i, (key, value) in enumerate(imgs.items()):
plt.subplot(1, 3, i+1)
plt.title(key)
plt.imshow(value, cmap='gray')
plt.xticks([]); plt.yticks([])
plt.show()

'Python' 카테고리의 다른 글
[OpenCV2] 이미지 연산 (0) | 2025.04.10 |
---|---|
[프로그래머스] 겹치는 선분의 길이 (0) | 2025.03.15 |
[프로그래머스] 순열과 조합을 이용한 문제 연습 (0) | 2025.02.16 |
[프로그래머스] deque을 활용한 문제 풀이 (0) | 2025.02.03 |
[프로그래머스] List 인덱싱을 활용한 문제 풀이 (1) | 2025.01.30 |
- #attention #deeplearning
- rnn #딥러닝 #시계열 데이터 #장기의존성 문제
- 자연어 처리 #정제 #정규표현식 #어간 추출 #표제어 추출
- python #프로그래머스 #리스트 #인덱싱
- #물고기 종류별 대어 찾기 #즐겨찾기가 가장 많은 식당 정보 출력하기 #mysql #programmers
- python #프로그래머스 #겹치는선분의길이
- nlp #토큰화 #nltk #konply
- #python #프로그래머스 #외계어사전 #itertools #순열과조합
- html #javascript #구구단 출력
- #opencv #이미지 연산 #합성
- randomforest #bagging #머신러닝 #하이퍼파라미터 튜닝
- #자연어 처리 #정수 인코딩 #빈도 수 기반
- gan #생성자 #판별자 #적대적 신경 신경망 #딥러닝 #computer vision
- python #deque #프로그래머스 #공 던지기 #문자열 계산하기 #코딩테스트
- 프로젝트 #머신러닝 #regression #eda #preprocessing #modeling
- #tf idf
- 파이썬 #코딩테스트 #프로그래머스 #스택 #큐
- 머신러닝 #lightgbm #goss #ebf
- #opencv #이미지 읽기 #이미지 제작 #관심영역 지정 #스레시홀딩
- ridge #lasso #정규화모델 #머신러닝
- 머신러닝 #project #classification #dacon
- 딥러닝 #오차역전파 #연쇄법칙 #계산그래프 #최적화
- subquery #sql 코딩테스트
- 로지스틱 회귀 #오즈비 #최대우도추정법 #머신러닝
- #seq2seq #encoder #decoder #teacher forcing
- pca #주성분분석 #특이값분해 #고유값분해 #공분산행렬 #차원의 저주
- 머신러닝 #xgboost #
- seaborn #데이터시각화 #타이타닉
- 잘라서 배열로 저장하기 #2차원으로 만들기
- 파이썬 #시각화 #matplotlib