OpenCV-Python 은 분수령 알고리즘 을 사용 하여 이미지 의 분할 과 추출 을 실현 합 니 다.

오늘날 세계 의 발전 에 따라 컴퓨터 시각 기술 의 응용 은 갈수 록 광범 위해 지고 있다.하드웨어 설비 가 계속 업그레이드 되면 서 구조 가 복잡 한 컴퓨터 시각 응용 이 점점 쉬 워 졌 다.OpenCV 는 마치 블랙 박스 처럼 우 리 는 시각 응용 개발 에 전념 하고 기초 이미지 처리 의 구체 적 인 세부 사항 에 지나치게 관심 을 가 질 필요 가 없다.
이미지 분할
분수령 알고리즘 을 이해 하기 전에 우 리 는 이미지 의 분할 이 무엇 인지 알 아야 한다.
그림 을 처리 하 는 과정 에서 그림 에서 전경 대상 을 대상 이미지 로 분할 하거나 추출 해 야 합 니 다.예 를 들 어 영상 감시 에서 관 측 된 것 은 고정된 배경 에서 의 영상 내용 인 데 우 리 는 배경 자체 에 관심 이 없고 배경 에 나타 난 차량,행인 또는 다른 대상 에 관심 이 있다.우 리 는 이 대상 들 을 동 영상 에서 추출 하고 대상 이 배경 에 들 어가 지 않 은 동 영상 내용 을 무시 하고 싶 습 니 다.
분수령 알고리즘
이미지 분할 은 이미지 처리 과정 에서 매우 중요 한 작업 이다.분수령 알고리즘 은 이미 지 를 지리학 상의 지형 표면 에 형상 적 으로 비유 하여 이미지 분할 을 실현 하 는데 이 알고리즘 은 매우 유용 하 다.
다음은 블 로 거들 이 분수령 알고리즘 에 관 한 내용 을 간단하게 소개 한다.(자세 한 내용 은 곤 살 레 스 의《디지털 이미지 처 리》라 는 책 을 참고 할 수 있다)
그 레이스 케 일 이미 지 는 지리학 적 지형 표면 으로 볼 수 있 고 그 레이스 케 일이 높 은 지역 일수 록 산봉우리 로 볼 수 있 으 며 그 레이스 케 일이 낮은 지역 일수 록 계곡 으로 볼 수 있다.
만약 우리 가 모든 계곡 에 서로 다른 색깔 의 물 을 주입 한다 면.그러면 수위 가 높 아 지면 서 계곡 마다 물이 모인다.이 과정 에서 서로 다른 계곡 의 물이 만 나 는 것 을 막 기 위해 서 는 물이 만 날 수 있 는 곳 에 제방 을 구축 해 야 한다.이 과정 은 이미 지 를 두 개의 서로 다른 집합 으로 나 누 었 다.집수 분지 와 분수령 선 이다.우리 가 세운 제방 은 바로 분수령 선,즉 원시 이미지 에 대한 분할 이다.이것 이 바로 분수령 산법 의 원리 다.
그러나 일반적인 이미지 에는 소음 이 존재 하기 때문에 분수령 알고리즘 을 사용 할 때 과도 한 분할 결 과 를 자주 얻 을 수 있다.이미지 분할 효 과 를 개선 하기 위해 사람들 은 마스크 를 바탕 으로 개 선 된 분수령 알고리즘 을 제시 했다.개 선 된 분수령 알고리즘 은 사용자 가 같은 분할 구역 의 부분 으로 표시 할 수 있 도록 합 니 다.이렇게 해서 분수령 알고리즘 은 처리 할 때 표 시 된 부분 을 같은 분할 구역 으로 처리한다.
이 이론 에 대해 잘 모 르 면 소프트웨어 파워 포인트 의'배경 삭제'기능 으로 관찰 하고 이해 할 수 있다.
waterShed 함수
OpenCV 에 서 는 함수 cv2.watershed()함 수 를 사용 하여 분수령 알고리즘 을 실현 할 수 있다.그러나 구체 적 으로 실현 되 는 과정 은 형태학 함수,거리 변환 함수 cv2.distance Transform(),cv2.connected Components()를 통 해 이미지 분할 을 완성 해 야 한다.
형태학 적 분할
분수령 알고리즘 을 사용 하기 전에 우 리 는 이미지 에 대해 간단 한 형태학 처 리 를 해 야 한다.일반적인 상황 에서 우 리 는 모두 형태학 에서 의 연산 을 사용한다.왜냐하면 연산 은 먼저 부식 한 후에 팽창 하 는 조작 이기 때문에 이미지 안의 소음 을 제거 할 수 있다.

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("36.jpg")
k=np.ones((5,5),dtype=np.uint8)
e=cv2.erode(img,k)
result=cv2.subtract(img,e)

plt.subplot(131)
plt.imshow(img, cmap="gray")
plt.axis('off')

plt.subplot(132)
plt.imshow(e, cmap="gray")
plt.axis('off')

plt.subplot(133)
plt.imshow(result, cmap="gray")
plt.axis('off')
plt.show()
돌 이 켜 보면 우리 앞의 연산 함 수 는 cv2.erode()이 고 여기 서 우 리 는 먼저 연산 을 통 해 소음 을 제거 합 니 다.그리고 cv2.subtract()를 줄 여 그림 경 계 를 가 져 옵 니 다.실행 후 효 과 는 다음 과 같 습 니 다.
效果
distanceTransform 함수
그림 속 의 각 하위 그림 이 연결 되 지 않 았 을 때 형태학 의 부식 작업 으로 전망 대상 을 직접 확인 할 수 있 지만 그림 속 의 하위 그림 이 연결 되 어 있 으 면 전망 대상 을 확정 하기 어렵다.이 럴 때 는 변환 함수 cv2.distance Transform()을 통 해 전경 대상 을 편리 하 게 추출 해 야 합 니 다.
cv2.distance Transform()은 각 픽 셀 점 과 배경(값 이 0 인 픽 셀 점)의 거리 관 계 를 반영 합 니 다.일반적인 상황 에서:
4.567917.전경 대상 의 중심 거리 가 0 인 픽 셀 점 거리 가 멀 면 비교적 큰 값 을 얻 을 수 있 습 니 다4.567917.전경 대상 의 가장자리 거리 가 0 인 픽 셀 점 이 가 까 우 면 작은 값 을 얻 을 수 있 습 니 다다음은 이 함 수 를 사용 하여 그림 의 전망 을 확인 하고 효 과 를 관찰 합 니 다.

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("36.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
k = np.ones((5, 5), dtype=np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, k, iterations=2)
distTransform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret, fore = cv2.threshold(distTransform, 0.7 * distTransform.max(), 255, 0)

plt.subplot(131)
plt.imshow(img, cmap="gray")
plt.axis('off')

plt.subplot(132)
plt.imshow(distTransform, cmap="gray")
plt.axis('off')

plt.subplot(133)
plt.imshow(fore, cmap="gray")
plt.axis('off')
plt.show()
여기 서 우 리 는 cv2.morphologyEx 함 수 를 사용 하여 연산 을 하 는 동시에 cv2.distance Transform 을 사용 하여 거리 이미 지 를 얻 고 마지막 으로 cv2.threshold 를 통 해 거리 이미지 에 대해 한도 값 처 리 를 하여 전망 을 확정 합 니 다.실행 후 효 과 는 다음 과 같 습 니 다.
前景
알 수 없 는 영역 확인
거리 함 수 를 통 해 우 리 는 이미지 의'중심',즉'전망 확인'을 얻 었 다.후속 설명 을 편리 하 게 하기 위해 서 우 리 는 전망 을 F 라 고 부 를 것 이다.
그림 에 전경 F 와 배경 B 를 확인 하고 나머지 구역 은 알 수 없 는 구역 UN 입 니 다.이 부분 은 바로 분수령 알고리즘 이 더욱 명확 해 야 할 구역 이다.
그림 0 에 대해 다음 관 계 를 통 해 알 수 없 는 영역 UN 을 얻 을 수 있 습 니 다.
알 수 없 는 영역 UN=그림 0-배경 확인 B-전경 확인 F
상기 공식 에서 다음 과 같이 변환 할 수 있다.
알 수 없 는 영역 UN=(그림 0-배경 B 확인)-전경 F 확인
그 중에서(이미지 0-배경 B 확인)은 바로 우리 가 시작 한 감법 조작 으로 형태학 의 팽창 을 통 해 얻 을 수 있다.위의 코드 를 4 줄 추가 하고 표시 되 는 코드 내용 을 변경 하기 만 하면 됩 니 다.

bg=cv2.dilate(opening,k,iterations=3)
fore=np.uint8(fore)
un=cv2.subtract(bg,fore)

plt.subplot(221)
plt.imshow(img, cmap="gray")
plt.axis('off')

plt.subplot(222)
plt.imshow(bg, cmap="gray")
plt.axis('off')

plt.subplot(223)
plt.imshow(fore, cmap="gray")
plt.axis('off')

plt.subplot(224)
plt.imshow(un, cmap="gray")
plt.axis('off')
plt.show()
실행 후 효 과 는 다음 과 같 습 니 다.
4附图
왼쪽 위 가 원본 그림 입 니 다.
오른쪽 위 는 원본 그림 이 팽창 한 후에 얻 은 그림 bg 이 고 배경 그림 은 배경 B 를 확인 합 니 다.전경 그림 은"원본 그림 0-배경 B 확인"입 니 다.
왼쪽 아래 전경 그림 을 확인 하기 위해 fore
오른쪽 아래 알 수 없 는 영역 그림 UN
ConnectedComponents 함수
전망 을 명 확 히 한 후에 전망 을 확정 하 는 것 에 대해 표시 할 수 있다.OpenCV 에서 cv2.Connected Components()함 수 를 제공 하여 표시 합 니 다.
이 함 수 는 배경 을 0 으로 표시 하고 다른 대상 을 1 부터 의 정수 로 표시 합 니 다.그것 은 8 개의 단일 채널 에 표 시 될 그림 만 있 습 니 다.
반환 값 은 두 가지 가 있 습 니 다.retval 은 되 돌아 오 는 레이 블 수량 이 고 labels 는 표 시 된 결과 그림 입 니 다.
다음은 이 함 수 를 사용 하여 표 시 를 하 겠 습 니 다.코드 는 다음 과 같 습 니 다.

bg = cv2.dilate(opening, k, iterations=3)
fore = np.uint8(fore)
ret, markets = cv2.connectedComponents(fore)
unknown=cv2.subtract(bg,fore)
markets=markets+1
markets[unknown==255]=0

plt.subplot(131)
plt.imshow(img, cmap="gray")
plt.axis('off')

plt.subplot(132)
plt.imshow(fore, cmap="gray")
plt.axis('off')

plt.subplot(133)
plt.imshow(markets, cmap="gray")
plt.axis('off')
plt.show()
위의 fore=np.uint 8(fore)코드 를 수정 하고 출력 내용 을 수정 합 니 다.실행 후,우 리 는 원본 그림,전경 이미지 의 중심 점 이미지 fore 와 표 시 된 결과 이미지 markeets 를 얻 을 수 있 습 니 다.효 과 는 다음 과 같 습 니 다:
效果图
실전 분수령 알고리즘
앞에서 소개 한 바 와 같이 우 리 는 분수령 알고리즘 을 사용 하여 이미지 분할 을 하 는 기본 적 인 절 차 를 이해 했다.
4.567917.형태학 적 연산 을 통 해 원시 이미지 0 을 소음 제거 합 니 다.4.567918.
  • 부식 작업 을 통 해'배경 B 확인'을 얻 을 수 있 습 니 다.주의해 야 할 것 은 여기 서'원본 이미지-배경 확인'을 얻 으 면 됩 니 다
  • 거리 변환 함 수 를 이용 하여 원시 이미 지 를 연산 하고 이 를 한도 값 으로 처리 하여'전망 F 확정'을 얻 었 다
  • 미 지 의 영역 UN(UN=0-B-F)을 계산 합 니 다함수 cv2.connected Components()를 이용 하여 원본 이미지 0 을 표시 합 니 다함수 cv2.connected Components()의 레이 블 결 과 를 수정 합 니 다분수령 함수 로 이미지 분할 완료
    전체 코드 는 다음 과 같 습 니 다:
    
    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    img = cv2.imread("36.jpg")
    plt.subplot(121)
    plt.imshow(img, cmap="gray")
    plt.axis('off')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    k = np.ones((5, 5), dtype=np.uint8)
    opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, k, iterations=2)
    distTransform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
    ret, fore = cv2.threshold(distTransform, 0.2 * distTransform.max(), 255, 0)
    bg = cv2.dilate(opening, k, iterations=3)
    fore = np.uint8(fore)
    ret, markets = cv2.connectedComponents(fore)
    unknown = cv2.subtract(bg, fore)
    markets = markets + 1
    markets[unknown == 255] = 0
    markets = cv2.watershed(img, markets)
    img[markets == -1] = [255, 0, 0]
    
    plt.subplot(122)
    plt.imshow(img, cmap="gray")
    plt.axis('off')
    plt.show()
    
    실행 한 후에 우 리 는 분 단 된 그림 을 얻 을 수 있 습 니 다.
    参数
    물론 매개 변 수 를 조정 할 수 있 고 대체적인 동전 이 완전히 분 할 된 것 을 볼 수 있다.
    여기 서 OpenCV-Python 이 분수령 알고리즘 을 사용 하여 이미지 의 분할 과 추출 을 실현 하 는 것 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 OpenCV 이미지 분할 과 추출 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

    좋은 웹페이지 즐겨찾기