티스토리 뷰
2025.04.05 - [Python] - [OpenCV 1] 이미지 실행 및 스레시홀딩
[OpenCV 1] 이미지 실행 및 스레시홀딩
OpenCv은 컴퓨터 비젼과 관련된 작업을 위한 강력하고 다양한 기능을 제공하는 Python의 이미지 전처리 라이브러리입니다. 주요 기능은 이미지의 기본적인 처리 작업(읽기 및 쓰기)과 필터링, 특징
up-one-coding.tistory.com
OpenCV 라이브러리와 numpy 연산을 활용하면 이미지 합성, 블렌딩, 이미지 간의 차이를 알 수 있습니다. 다만 주의해야 할 점은 연산 결과로 픽셀 값이 255가 넘거나 0보다 작아지면 이미지가 깨지는 상태가 발생하기 때문에 반드시 0에서 255 사이의 값이 출력되도록 처리를 진행해야 합니다.
1. mask을 이용한 누적할당과 비교연산
mask은 연산을 진행할 픽셀의 위치를 지정하는 역할을 합니다. mask의 값이 [1, 0]인 경우 0이 아닌 위치에 있는 픽셀만 연산을 진행한다고 볼 수 있습니다.
#mask을 이용한 누적할당
a = np.array([[1,2]],dtype=np.uint8) #np.uint8은 범위가 0~255이므로 255초과값부터 다시 0으로 계산
b = np.array([[10,20]],dtype=np.uint8)
mask = np.array([[1,0]],dtype=np.uint8)
#누적할당과의 비교 연산
cal1 = cv2.add(a,b,None,mask)
cal2 = cv2.add(a,b,b.copy(),mask) ##mask로 연산이 안된 자리를 b로 대체
cal3 = cv2.add(a,b,a.copy(),mask) #mask로 연산이 안된 자리를 a로 대체
print(cal1) #[[11 0]]
print(cal2) #[[11 20]]
print(cal3) #[[11 2]]
cal1의 결과는 1과 10만 덧셈을 진행하고 2와 20은 연산을 진행하지 않은 것을 볼 수 있습니다. 즉 mask 배열에 의해 1로 지정된 위치의 픽셀 값끼리만 연산이 진행된 것을 확인할 수 있습니다. 누적 할당은 연산을 진행하지 않은 부분에 b의 값을 넣어 출력되게끔 하는 것입니다. add 함수에 b가 아닌 b.copy()을 넣은 이유는 b의 값이 원본이 아닌 cal2값을 가지는 것을 방지하는 방법이 존재합니다.
2. 알파 블렌딩
알파 블렌딩은 제대로 된 이미지 합성을 위해서 가중치를 부여하는 방법입니다. 기존 방법처럼 단순히 두 이미지를 연산하면 픽셀 값이 깨지는 현상이 발생합니다.
#numpy을 이용한 알파블렌딩
alpha=0.5
result = img1*alpha + img2*(1-alpha)
result = result.astype(np.uint8) #소수점을 제거하고 값을 0~255로 만들기
#cv2을 이용한 알파블렌딩
result2 = cv2.addWeighted(img1, alpha, img2, 0.2,0)
imgs = {'result1':result,
'result2':result2}
for i, (k,v) in enumerate(imgs.items()):
plt.subplot(1,2,i+1),plt.axis('off'),plt.imshow(v[:,:,::-1]),plt.title(k)
비트와이즈 연산은 두 이미지의 비트 단위로 연산을 진행하며, 두 이미지를 합성할 때 특정 영역만 선택할 때 유용한 방법입니다.
#이미지 생성
img1 = np.zeros((200,400),dtype=np.uint8)
img2 = np.zeros((200,400),dtype=np.uint8)
#img slicing
img1[:,:200] = 255 #왼쪽은 검은색, 오른쪽은 흰색
img2[100:200,:] = 255 #위쪽은 검은색, 아래쪽은 흰색
#비트와이즈 연산
bitAnd = cv2.bitwise_and(img1,img2)
bitOr = cv2.bitwise_or(img1,img2)
bitXor = cv2.bitwise_xor(img1, img2)
bitNot = cv2.bitwise_not(img1)
imgs = {'img1':img1, 'img2':img2,
'And':bitAnd, 'Or':bitOr,
'Xor':bitXor, 'Not':bitNot}
fig = plt.figure(figsize=(10, 8))
for i, (title, img) in enumerate(imgs.items()):
plt.subplot(3,2,i+1)
plt.title(title)
plt.imshow(img, 'gray')
plt.xticks([]); plt.yticks([])
plt.show()
0이 검은색, 1이 흰색을 의미할 때, AND 연산을 진행하면 두 이미지의 흰색 부분이 겹치는 위치만 흰색으로 표시되는 것을 알 수 있습니다. XOR 연산은 두 비트가 다를 때 1을 반환하고, 같을 때 0을 반환하는 연산임을 확인할 수 있습니다.
3. 두 이미지의 차이
openCV의 뺄셈 연산은 두 이미지 사이의 차이를 확인할 때 유용합니다. 다만 두 이미지 픽셀 값의 차이는 음수가 나올 수 있기 때문에 두 이미지의 차이를 절댓값으로 변환하는 것이 필요합니다.
#두 이미지의 차이
#두 이미지의 픽셀 값을 빼면 음수가 나올 수 있으므로, 절댓값을 취해야한다
img1 = cv2.imread('./drawing1.jpg')
img2 = cv2.imread('./drawing2.jpg')
img1_GRAY = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
img2_GRAY = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
#두 이미지의 절대값 차 연산
diff = cv2.absdiff(img1_GRAY, img2_GRAY)
#차이를 극대화하기 위한 스레시홀드 처리 및 컬러 변환
#픽셀 값이 1보다 큰 값은 255로 변환, 그렇지 않은 픽셀값은 0으로 변환
_,diff = cv2.threshold(diff,1,255,cv2.THRESH_BINARY)
diff_red = cv2.cvtColor(diff, cv2.COLOR_GRAY2BGR)
diff = cv2.cvtColor(diff, cv2.COLOR_GRAY2BGR)
diff_red[:,:,0] = 0
#변화를 빨강색으로 표시
spot = cv2.bitwise_xor(img2, diff_red)
#출력
fig = plt.figure(figsize=(20, 16))
plt.subplot(221), plt.axis('off'), plt.imshow(img1), plt.title("img1")
plt.subplot(222), plt.axis('off'), plt.imshow(img2), plt.title("img2")
plt.subplot(223), plt.axis('off'), plt.imshow(diff), plt.title("diff")
plt.subplot(224), plt.axis('off'), plt.imshow(spot), plt.title("spot")
plt.show()
예시 이미지에 따르면, 오른쪽 대각선 위 점 4개가 img2에는 존재하지 않은 것을 볼 수 있습니다. 두 이미지의 차이를 구하는 연산과 그 차이를 강조하기 위한 쓰레시홀딩 기법을 활용하면 위와 같은 결과처럼 차이를 명확하게 확인할 수 있습니다.
4. 이미지 합성
두 이미지(전경, 배경)를 합성하기 위해서는 mask 기법을 활용해야 합니다. mask을 이용해서 전경 이미지만 남기고, mask_inv을 이용해서 배경 이미지의 해당 영역을 남기는 것입니다. 이 영역은 전경이 들어갈 영역만 투명하게 처리하는 것입니다.
img_bg = cv2.imread('./dog.jpg')
img_fg = cv2.imread('./opencv_logo.png',cv2.IMREAD_UNCHANGED)
#알파채널을 이용해서 마스크와 역마스크 생성
_,mask = cv2.threshold(img_fg[:,:,3],1,255,cv2.THRESH_BINARY)
mask_inv = cv2.bitwise_not(mask)
#이미지 크기로 배경 사진에서 관심영역 잘라내기
img_fg = cv2.cvtColor(img_fg, cv2.COLOR_BGRA2BGR)
h,w = img_fg.shape[:2]
roi = img_bg[10:10+h, 10:10+w] #전경을 합성할 위치
#mask을 이용해서 오려내기
masked_fg = cv2.bitwise_and(img_fg, img_fg, mask=mask)
masked_bg = cv2.bitwise_and(roi,roi,mask=mask_inv)
#이미지 합성
added = masked_fg+masked_bg
img_bg[10:10+h, 10:10+w] = added
#이미지 color맵 발생
mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2RGB)
added = cv2.cvtColor(added, cv2.COLOR_BGR2RGB)
fig = plt.figure(figsize=(10, 8))
plt.subplot(231), plt.axis('off'), plt.imshow(mask), plt.title("mask")
plt.subplot(232), plt.axis('off'), plt.imshow(added), plt.title("added")
plt.show()
'Python' 카테고리의 다른 글
[프로그래머스] 안전지대 (0) | 2025.05.20 |
---|---|
[OpenCV 1] 이미지 실행 및 스레시홀딩 (0) | 2025.04.05 |
[프로그래머스] 겹치는 선분의 길이 (0) | 2025.03.15 |
[프로그래머스] 순열과 조합을 이용한 문제 연습 (0) | 2025.02.16 |
[프로그래머스] deque을 활용한 문제 풀이 (0) | 2025.02.03 |
- python #프로그래머스 #겹치는선분의길이
- 머신러닝 #xgboost #
- subquery #sql 코딩테스트
- 머신러닝 #lightgbm #goss #ebf
- gan #생성자 #판별자 #적대적 신경 신경망 #딥러닝 #computer vision
- #attention #deeplearning
- nlp #토큰화 #nltk #konply
- 딥러닝 #오차역전파 #연쇄법칙 #계산그래프 #최적화
- #seq2seq #encoder #decoder #teacher forcing
- pca #주성분분석 #특이값분해 #고유값분해 #공분산행렬 #차원의 저주
- randomforest #bagging #머신러닝 #하이퍼파라미터 튜닝
- 파이썬 #코딩테스트 #프로그래머스 #스택 #큐
- #자연어 처리 #정수 인코딩 #빈도 수 기반
- 프로젝트 #머신러닝 #regression #eda #preprocessing #modeling
- rnn #딥러닝 #시계열 데이터 #장기의존성 문제
- html #javascript #구구단 출력
- #tf idf
- python #프로그래머스 #리스트 #인덱싱
- #opencv #이미지 연산 #합성
- 파이썬 #시각화 #matplotlib
- #opencv #이미지 읽기 #이미지 제작 #관심영역 지정 #스레시홀딩
- #프로그래머스 #안전지대 #시뮬레이션
- seaborn #데이터시각화 #타이타닉
- 자연어 처리 #정제 #정규표현식 #어간 추출 #표제어 추출
- #물고기 종류별 대어 찾기 #즐겨찾기가 가장 많은 식당 정보 출력하기 #mysql #programmers
- python #deque #프로그래머스 #공 던지기 #문자열 계산하기 #코딩테스트
- 로지스틱 회귀 #오즈비 #최대우도추정법 #머신러닝
- 머신러닝 #project #classification #dacon
- #python #프로그래머스 #외계어사전 #itertools #순열과조합
- 잘라서 배열로 저장하기 #2차원으로 만들기