OpenCV의 이미지 처리 - Contour + Contour 기능 소개

OpenCV의 이미지 처리 - Contour + Contour 기능 소개

1. OpenCV의 컨투어

1.1 프로필 개요

항상 똑같습니다.OpenCV에서 윤곽선에 대해 알아보기 전에 윤곽선이 무엇인지 알아보겠습니다.윤곽선은 단순히 모든 연속된 점(경계를 따라)을 동일한 색상 또는 강도로 연결하는 곡선으로 해석할 수 있습니다.윤곽선은 도형에 사용됩니다. 유용함 분석 및 객체와 감지 및 인식을 위한 도구

  • 정확도를 높이기 위해 이진 이미지를 사용하므로 윤곽선을 찾기 전에 임계값 또는 캐니 에지 감지를 적용합니다.
  • OpenCV에서 윤곽선을 찾는 것은 검은색 배경에서 흰색 물체를 찾는 것이므로 찾고자 하는 물체는 흰색이고 배경은 검은색이어야 합니다(임계값 또는 캐니 에지 감지 적용 후).

이진 이미지의 이미지를 찾으려면 cv.findContours() 함수를 사용해야 합니다 . 이 함수에는 세 개의 매개 변수가 포함되어 있습니다. 첫 번째는 원본 이미지이고 두 번째는 윤곽 검색 모드이고 세 번째는 윤곽 근사입니다. 이 함수는 윤곽선과 계층 구조를 출력하고 윤곽선은 이미지의 모든 이미지에 대한 Python 목록을 참조하며 각 개별 윤곽선은 경계점의 (x,y) 좌표 개체의 Numpy 배열입니다.

import numpy as np
import cv2 as cv
im = cv.imread('test.jpg')
imgray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,
cv.CHAIN_APPROX_SIMPLE)

두 번째 매개변수 윤곽선 검색 모드의 값은 다음과 같습니다.

  • RETR_EXTERNAL: 가장 바깥쪽 윤곽만 검색

  • RETR_LIST: 모든 윤곽선을 검색하여 연결 목록에 저장

  • RETR_CCOMP: 모든 컨투어를 검색하여 두 개의 레이어로 구성합니다. 맨 위 레이어는 부품의 외부 경계이고 두 번째 레이어는 캐비티의 경계입니다.

  • RETR_TREE: 공통, 모든 윤곽선을 검색하고 중첩된 윤곽선의 전체 계층 구조를 재구성합니다. 모든 개요 저장

세 번째 매개변수 윤곽 근사화 방법의 값은 다음과 같습니다.

  • CHAIN_APPROX_NONE: 윤곽선을 Freeman 체인 코드로 출력하고 다른 모든 방법은 다각형(정점 시퀀스)을 출력합니다. 모든 등고선을 정상적으로 그립니다.

  • CHAIN_APPROX_SIMPLE: 수평, 수직 및 사선 부분을 압축합니다. 즉, 함수는 끝점 좌표만 유지합니다. 압축을 하면 보다 간소화된 결과를 얻을 수 있습니다. 예를 들어 직사각형 아웃라인은 아웃라인 정보를 저장하는 데 4포인트만 필요합니다.

데이터 참조는 기사에서 가져옵니다: [opencv] (6) 이미지 윤곽 처리

1.2 윤곽선 그리기

cv.findContours() 함수를 통해 윤곽선을 찾은 후 일반적으로 cv.drawContours() 함수를 통해 윤곽선을 그립니다.경계점이 있으면 어떤 모양이든 그릴 수 있습니다.첫번째 매개변수 이 함수의 이미지 리소스는 이미지 리소스, 두 번째 매개변수는 파이썬 목록으로 전달해야 하는 윤곽선, 세 번째 매개변수는 윤곽선의 인덱스입니다(단일 윤곽선을 그릴 때 유용하며 모든 윤곽선을 그려야 하는 경우 전달합니다. 매개변수 -1), 나머지 매개변수는 색상 두께와 같은 공통 매개변수입니다.

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('E:/image/test09.png')
# 在寻找轮廓时要传入单通道图像
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, threshold = cv.threshold(gray, 127, 255, cv.THRESH_BINARY)
contours, hierarchy = cv.findContours(threshold, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# 绘制所有轮廓
img1 = cv.drawContours(img, contours, -1, (0, 255, 0), 3)
# 绘制单个轮廓
img2 = cv.drawContours(img, contours, 3, (0, 255, 0), 3)
# 常用的绘制轮廓的方法
cnt = contours[3]
img3 = cv.drawContours(img, [cnt], 0, (0, 255, 0), 3)
plt.subplot(1, 3, 1), plt.imshow(img, cmap='gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1, 3, 2), plt.imshow(img, cmap='gray')
plt.title('ALL_IMG'), plt.xticks([]), plt.yticks([])
plt.subplot(1, 3, 3), plt.imshow(img, cmap='gray')
plt.title('Usually'), plt.xticks([]), plt.yticks([])
plt.show()

여기에 이미지 설명 삽입

1.3 등고선 근사법

앞에서 언급한 cv.findContours() 함수는 전달해야 할 세 개의 매개변수가 있으며, 세 번째 매개변수는 윤곽 근사법으로 여기서 이야기할 윤곽 근사법입니다. 윤곽선은 같은 강도를 가진 도형의 경계로, 도형 경계의 (x,y) 좌표를 저장하지만 모든 좌표를 저장하지는 않습니다.

그리고 모든 좌표를 저장하는지 여부는 윤곽근사법을 사용하느냐에 따라 달라지며, cv.CHAIN_APPROX_NONE 매개변수를 전달하면 윤곽선은 모든 좌표를 저장하게 되지만 실제 상황에서는 모든 좌표를 저장해야 할까요? ? ?

예를 들어 직사각형 윤곽선을 찾은 경우 모든 좌표를 저장하면 많은 공간이 낭비됩니다. 꼭지점 4개의 좌표만 저장하면 됩니다.

2. 윤곽선 특징

2.1 특징적인 순간

특징적 모멘트를 배우기 전에 먼저 그 개념을 이해해야 하는데, 먼저 특징적 모멘트는 윤곽선과 이미지의 전체적인 특징을 의미하며, 모멘트 정보는 해당 객체의 다양한 형태의 기하학적 특징을 담고 있다. 유형: 공간 모멘트, 중심 모멘트 및 정규화된 중심 모멘트

중심 모멘트: 고차 이미지의 경우 위치의 변화에 ​​따라 특성 모멘트가 달라지게 되는데 이를 해결하기 위해 중심 모멘트가 생겨났으며 평균값을 빼서 병진의 불변성을 구하여 비교할 수 있다. 서로 다른 위치에 있는 두 개의 이미지 개체가 일치하는지 여부, 즉 중심 모멘트가 병진 불변의 특성을 가짐

정규화된 중심 모멘트: 번역 외에도 일부 이미지는 확대/축소도 발생합니다.즉, 확대/축소 후에도 특성을 판단할 수 있습니다.정규화된 중심 모멘트는 개체의 전체 크기로 나누어 줌 불변성을 구합니다.

OpenCV 기능 순간으로 돌아가서 중심, 면적 등과 같은 일부 기능을 계산하는 데 도움이 될 수 있습니다. 중요한 함수 cv.moments()는 계산된 모든 순간 값의 사전을 제공합니다.

import numpy as np
import cv2 as cv
img = cv.imread('star.jpg',0)
ret,thresh = cv.threshold(img,127,255,0)
contours,hierarchy = cv.findContours(thresh, 1, 2)
cnt = contours[0] 
M = cv.moments(cnt)
print( M )

2.2 등고선 영역 + 둘레

컨투어 영역은 cv.contourArea () 함수 또는 M['m00'] 순간부터 제공됩니다.

둘레는 호 길이라고도 하며 cv.arcLength () 함수를 사용하여 찾을 수 있습니다. 두 번째 매개변수는 모양이 닫힌 윤곽선인지( True ) 곡선인지 지정합니다.

area = cv.contourArea(cnt)
perimeter = cv.arcLength(cnt,True)

2.3 등고선 근사

Contour approximation은 우리가 지정한 집중 읽기에 따라 Douglas-Puk 알고리즘을 통해 더 적은 꼭지점으로 다른 모양으로 윤곽 모양을 근사하는 것입니다.

Douglas-Puke 알고리즘에 관해서는 그 본질을 살펴봐야 합니다. 이미지를 디지털화할 때 곡선이 샘플링됩니다. 어느 정도 원래의 어떤 모양

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

src = cv2.imread('E:/image/test10.png')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(~thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]
img1 = src.copy()
epslion1 = 0.05 * cv2.arcLength(cnt, True)
approx1 = cv2.approxPolyDP(cnt, epslion1, True)
img1 = cv2.drawContours(img1, [approx1], 0, (0, 0, 255), 2)
img2 = src.copy()
epslion2 = 0.01 * cv2.arcLength(cnt, True)
approx2 = cv2.approxPolyDP(cnt, epslion2, True)
img2 = cv2.drawContours(img2, [approx2], 0, (0, 255, 0), 2)
plt.subplot(1, 2, 1), plt.imshow(img1, cmap='gray')
plt.title('JinSi1'), plt.xticks([]), plt.yticks([])
plt.subplot(1, 2, 2), plt.imshow(img2, cmap='gray')
plt.title('JInSi2'), plt.xticks([]), plt.yticks([])
plt.show()

여기에 이미지 설명 삽입

이전 지식의 복습으로 이미지의 대략적인 윤곽을 다른 정밀도로 두 개 그리는 전체 프로세스를 분석합니다.먼저 필요한 타사 라이브러리를 로드하여 코드에서 메서드를 사용할 수 있도록 한 다음 코드의 5번째 줄에서 cv,imread() 함수를 통해 이미지를 읽은 다음 cv.cvtColor() 함수를 사용하여 그레이 스케일 이미지로 변환하는데 왜 이를 그레이 스케일 이미지로 변환해야 합니까? 다음에 이미지 임계값을 사용할 것이기 때문입니다! 전역 임계값 함수 cv.threshold() 함수에는 전달해야 할 매개변수가 4개 있습니다. 첫 번째 매개변수는 원본 이미지로 일반적으로 회색조 이미지이므로 img를 회색으로 변경해야 합니다. 두 번째 매개변수는 첫 번째 매개변수는 우리가 설정한 임계값으로 이미지의 픽셀을 분류하는 데 사용되며 임계값보다 큰 픽셀은 최대값으로 설정되고 세 번째 매개변수는 우리가 설정한 최대값이며 네 번째 매개변수는 다양한 유형의 기호 표현

코드는 8번째 줄에 도달합니다. 이제부터는 이 부분에서 배운 내용을 포함할 것입니다. 첫 번째로 예봉을 감당해야 할 것은 윤곽선을 찾는 것입니다. 우리는 cv.findContours() 함수를 사용합니다. 이 세 가지 매개변수는 기능은 이미지 및 윤곽 검색 모드이며 윤곽 근사 방법입니다.

11행에서 기묘한 것이 나타났는데 윤곽근사 핵심코드 중 하나인데 Epslion은 근사정확도와 밀접한 관련이 있는 매개변수로 윤곽선에서 근사윤곽선까지의 최대 거리를 나타낸다. 그런 다음 함수를 사용해야 합니다.

11줄의 코드 중 0.05를 0.1로 바꾸면 우리가 원하는 출력을 얻을 수 없다는 것을 알게 될 것입니다.

2.4 볼록 선체

윤곽 볼록 껍질과 윤곽 근사는 비슷해 보이지만 실제로는 서로 관련이 없습니다. 윤곽 볼록 껍질과 관련하여 중요한 기능인 cv.convexHull() 함수도 있습니다. 볼록하고 오목한 결함이 있고 수정하십시오.수정 없음, 이 기능의 매개 변수에 따라 다름

일반적으로 볼록한 곡선은 일반적으로 볼록하거나 평평한 곡선이며 내부가 볼록(오목)하면 볼록 결함이라고 합니다. 볼록 결함에 대해서는 나중에 자세히 설명하겠습니다.

함수 cv.convexHull()의 구문에 대해 이야기해 보겠습니다.

hull = cv.convexHull(points[, hull[, clockwise[, returnPoints]]

점은 우리가 통과한 윤곽선입니다 (왜 점을 사용합니까? 윤곽선의 본질은 동일한 색상이나 강도를 가진 모든 연속 점으로 연결된 곡선이라는 것을 잊으셨습니까?), 헐(팽창)은 출력이며, 우리는 일반적으로 무시됩니다, clockwise는 방향 표시이며 True로 전달되면 시계 방향이고 그렇지 않으면 시계 반대 방향입니다. returnPoint는 기본적으로 True이며 볼록 선체의 좌표를 반환하고 False이면 볼록에 해당하는 점을 반환합니다. 선체 윤곽점의 인덱스

그런 다음 예제로 이동하십시오! (꾸준히 연습해서 성장하세요!)

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

src = cv2.imread('E:/image/test11.png')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 寻找轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
    hull = cv2.convexHull(cnt)
    length = len(hull)
    # 如果凸包点集中的点个数大于5
    if length > 5:
        # 绘制图像凸包的轮廓
        for i in range(length):
            cv2.line(src, tuple(hull[i][0]), tuple(hull[(i + 1) % length][0]), (0, 0, 255), 2)
cv2.imshow('line', src)
cv2.waitKey()

여기에 이미지 설명 삽입

기사 참조 소스: 이미지의 볼록 껍질(convex hull)을 찾기 위한 OpenCV 항목

2.5 경계 사각형(직각 사각형 + 회전 사각형)

2.5.1 직각 사각형

직각 사각형은 객체의 회전을 고려하지 않으므로 직각 경계 사각형의 면적이 가장 작지 않습니다. 이 사각형을 찾는 데는 cv.boundingRect() 함수가 포함됩니다.

# (x,y)为左上角坐标,(w,h)为宽和高
x,y,w,h = cv.boundingRect(cnt)
cv.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)

2.5.2 사각형 회전

회전된 경계 사각형은 최소 면적으로 그려지므로 객체의 회전을 고려합니다.회전된 경계 사각형을 찾는 데 관련된 함수는 cv.minAreaRect()이며 좌표, 너비, 높이를 포함하는 Box2D 구조를 반환합니다. , 회전 각도 , 하지만 우리는 이 직사각형을 얻고 싶습니다. 꽤 번거롭습니다. 네 꼭지점의 좌표가 필요합니다.

rect = cv.minAreaRect(cnt)
box = cv.boxPoints(rect)
box = np.int0(box)
cv.drawContours(img,[box],0,(0,0,255),2)

2.8 최소 폐원 + 피팅 타원

2.8.1 최소 폐원

개체의 최소 둘러싸는 원을 찾으려면 cv.minEnclosingCircle() 함수를 사용해야 합니다. 이 함수는 가장 작은 영역으로 개체를 완전히 덮는 원입니다.

(x,y),radius = cv.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
cv.circle(img,center,radius,(0,255,0),2)

2.8.2 타원 맞추기

개체의 타원을 맞추려면 cv.fitEllipse() 함수를 사용합니다.

ellipse = cv.fitEllipse(cnt)
cv.ellipse(img,ellipse,(0,255,0),2)

애플리케이션 코드를 살펴보겠습니다.

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

img = cv2.imread('E:/image/test13.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 设置阈值
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]
x, y, w, h = cv2.boundingRect(cnt)
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
img = cv2.drawContours(img, [box], 0, (0, 0, 255), 2)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyWindow()

여기에 이미지 설명 삽입


(참고: 기사의 내용은 OpenCV4.1의 공식 중국어 문서를 참조하십시오.)
기사가 도움이 되었다면 클릭 한 번과 세 개의 링크로 지원하는 것을 잊지 마십시오.

Supongo que te gusta

Origin blog.csdn.net/qq_50587771/article/details/123819620
Recomendado
Clasificación