OpenCV-Python 색상 인식(빨간색) 및 맞춤 보정 대상 영역

OpenCV 버전: 4.6.0.66

알고리즘 구현 아이디어:

  1. 색상 인식(빨간색)
  2. 형태학적 노이즈 제거
  3. 윤곽 감지
  4. 폴리곤 피팅
  5. 원근 교정

암호:

import cv2
import numpy as np


# 可视化
def img_show(name, img):
    cv2.namedWindow(name, 0)
    cv2.resizeWindow(name, 1000, 500)
    cv2.imshow(name, img)
    cv2.waitKey(0)


def color_warped(path):
    img = cv2.imread(path)
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    # 颜色识别(红色),过滤红色区域
    lower_red1 = np.array([0, 43, 46])  # 红色阈值下界
    higher_red1 = np.array([10, 255, 255])  # 红色阈值上界
    mask_red1 = cv2.inRange(hsv, lower_red1, higher_red1)
    lower_red2 = np.array([156, 43, 46])  # 红色阈值下界
    higher_red2 = np.array([180, 255, 255])  # 红色阈值上界
    mask_red2 = cv2.inRange(hsv, lower_red2, higher_red2)
    mask_red = cv2.add(mask_red1, mask_red2)  # 拼接过滤后的mask
    img_show('mask_red', mask_red)

    # 形态学去噪,cv2.MORPH_OPEN先腐蚀再膨胀,cv2.MORPH_CLOSE先膨胀再腐蚀
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
    mask_red = cv2.morphologyEx(mask_red, cv2.MORPH_OPEN, kernel, iterations=1)
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7))
    mask_red = cv2.morphologyEx(mask_red, cv2.MORPH_CLOSE, kernel, iterations=3)
    img_show('mask_red', mask_red)

    # 轮廓检测,找出线条的轮廓
    draw_cnt = img.copy()
    cnts = cv2.findContours(mask_red, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
    cv2.drawContours(draw_cnt, cnts, -1, (0, 255, 0), 2)
    img_show('draw_cnt', draw_cnt)

    # 四边形拟合,找到相应的的顶点
    draw_approx = img.copy()
    point1, point2 = list(), list()
    for cnt in cnts:
        for epsilon in range(50):
            approx = cv2.approxPolyDP(cnt, epsilon, True)
            if len(approx) == 4:
                break
        cv2.polylines(draw_approx, [approx], True, (0, 0, 255), 2)  # 绘制边
        for i in approx:
            cv2.circle(draw_approx, i[0], 6, (0, 0, 0), -1)  # 绘制顶点

        approx = [i[0] for i in approx.tolist()]
        approx = sorted(approx, key=lambda k: k[1], reverse=False)  # 按y坐标排序,升序

        point1.extend(approx[:2])  # 存放上顶点坐标
        point2.extend(approx[2:])  # 存放下顶点坐标
    point1.sort(key=lambda k: k[0], reverse=False)  # 按x坐标排序,升序
    point2.sort(key=lambda k: k[0], reverse=False)
    img_show('draw_approx', draw_approx)

    # 透视矫正目标区域
    w, h = 900, 300
    rect = [point1[0], point1[-1], point2[-1], point2[0]]  # 顺序为第一个四边形的左上,第四个四边形的右上,第四个四边形的右下,第一个四边形的左下
    pts1 = np.array(rect, dtype="float32")
    pts2 = np.array([rect[0], [rect[0][0] + w, rect[0][1]],
                    [rect[0][0] + w, rect[0][1] + h], [rect[0][0], rect[0][1] + h]], dtype="float32")
    M = cv2.getPerspectiveTransform(pts1, pts2)  # 变换矩阵
    img_warped = cv2.warpPerspective(img, M, (1500, 500))  # 透视变换
    img_show('img_warped1', img_warped)

    img_warped = img_warped[rect[0][1]: rect[0][1] + h, rect[0][0]: rect[0][0] + w]  # 抠出变换后的区域
    img_show('img_warped2', img_warped)


if __name__ == '__main__':
    path = 'data/picture/18.jpg'
    color_warped(path)

원본 이미지:

색상 인식(빨간색)

img = cv2.imread(path)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

        색상 인식에 사용되는 채널은 HSV 채널입니다. HSV 채널을 사용하여 색상을 식별하는 것이 BGR 채널을 사용하는 것보다 쉽게 ​​구분할 수 있습니다. H는 색조 (hue, 색조, 값: 0-180), S는 채도 (채도, 색상 순도, 값: 0-255), V는 (밝기, 값: 0-255), 자세히 표시: HSV 색상 공간 . 각 색상의 값 범위는 다음과 같습니다.

빨간색 에 대해 두 가지 값 범위가 있음          을 알 수 있으며 이 두 범위는 대부분의 경우 보완적일 뿐이며 실제 상황에 따라 조정할 수 있습니다.

# 颜色识别(红色),过滤红色区域
lower_red1 = np.array([0, 43, 46])  # 红色阈值下界
higher_red1 = np.array([10, 255, 255])  # 红色阈值上界
mask_red1 = cv2.inRange(hsv, lower_red1, higher_red1)
lower_red2 = np.array([156, 43, 46])  # 红色阈值下界
higher_red2 = np.array([180, 255, 255])  # 红色阈值上界
mask_red2 = cv2.inRange(hsv, lower_red2, higher_red2)
mask_red = cv2.add(mask_red1, mask_red2)  # 拼接过滤后的mask

         필터링된 바이너리 이미지는 다음과 같습니다.

형태학적 노이즈 제거

# 形态学去噪,cv2.MORPH_OPEN先腐蚀再膨胀,cv2.MORPH_CLOSE先膨胀再腐蚀
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
mask_red = cv2.morphologyEx(mask_red, cv2.MORPH_OPEN, kernel, iterations=1)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7))
mask_red = cv2.morphologyEx(mask_red, cv2.MORPH_CLOSE, kernel, iterations=3)

색상 인식은 노이즈          의 일부를 함께 인식하는 경우가 있는데 , 이때 노이즈 제거를 위해 모폴로지를 사용할 수 있습니다. 형태학적 노이즈 제거를 위해 cv2.morphologyEx를 사용하기 전에 컨볼루션 커널모양크기를 cv2.getStruturingElement 로 정의해야 합니다 .

        cv2.getStruturingElement(shape, ksize)의 공통 매개변수 는 다음과 같습니다.

  • shape: 커널의 모양, cv2.MORPH_RECT ( 사각형 ), cv2.MORPH_CROSS ( 십자형 ), cv2.MORPH_ELLIPSE ( 타원형 )
  • ksize: (너비, 높이) 형식의 코어 크기

        cv2.morphologyEx(src, op, kernel, iterations)의  공통 매개변수 는 다음과 같습니다.

  • src: 입력 이미지
  • op: 형태학적 연산의 유형, cv2.MORPH_ERODE ( 침식 ), cv2.MORPH_DILATE ( 팽창 ), cv2.MORPH_OPEN ( 열기 연산 ), cv2.MORPH_CLOSE ( 닫기 연산 ), cv2.MORPH_GRADIENT ( 그래디언트 연산 ), cv2.MORPH_TOPHAT ( Top hat 연산 ), cv2.MORPH_BLACKHAT ( 검은 모자 연산 ), 자세한 내용 보기: Morphological 연산
  • 커널: 형태학적 연산을 위한 컨볼루션 커널
  • iterations: 형태학적 연산 반복 횟수, 기본값은 1

        효과는 다음과 같습니다.

윤곽 감지

# 轮廓检测,找出线条的轮廓
draw_cnt = img.copy()
cnts = cv2.findContours(mask_red, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
cv2.drawContours(draw_cnt, cnts, -1, (0, 255, 0), 2)

cv2.findContours(image, mode, method)를         사용하여 윤곽선을 감지합니다. 공통 매개변수는 다음과 같습니다.

  • 이미지: 이진 이미지
  • mode: 윤곽선 검색 모드
cv2.RETR_EXTERNAL 외부 윤곽만 감지
cv2.RETR_LIST 감지된 윤곽선은 계층적 관계를 설정하지 않습니다.
cv2.RETR_CCOMP 2단계 등고선이 설정되며, 상위 레이어는 외부 경계이고 내부 레이어는 내부 구멍의 경계 정보입니다. 내부 구멍에 연결된 다른 객체가 있으면 이 객체의 경계도 최상위 레이어에 있습니다.
cv2.RETR_TREE 계층적 트리 구조의 개요 작성
  • method: 윤곽선의 근사화 방법
cv2.CHAIN_APPROX_NONE 모든 윤곽점을 저장하고 인접한 두 점 사이의 픽셀 위치 차이는 1을 초과하지 않습니다.
cv2.CHAIN_APPROX_SIMPLE 가로 방향, 세로 방향, 대각선 방향의 요소를 압축하고 방향의 끝 좌표만 유지

cv2.drawContours를          사용하여 윤곽선을 그립니다. 효과는 다음과 같습니다.

대략적인 다각형

# 四边形拟合,找到相应的的顶点
draw_approx = img.copy()
point1, point2 = list(), list()
for cnt in cnts:
    for epsilon in range(50):
        approx = cv2.approxPolyDP(cnt, epsilon, True)
        if len(approx) == 4:
            break
    cv2.polylines(draw_approx, [approx], True, (0, 0, 255), 2)  # 绘制边
    for i in approx:
        cv2.circle(draw_approx, i[0], 6, (0, 0, 0), -1)  # 绘制顶点

cv2.approxPolyDP(curve, epsilon, closed)를         사용하여 다각형을 근사화합니다. 공통 매개변수는 다음과 같습니다.

  • 곡선: 입력된 2차원 점 집합 의 배열
  • 엡실론: 대략적인 결과의 정밀도 . 이것은 원래 곡선과 그 근사치 사이의 최대 거리입니다. 엡실론이 작을수록 근사 결과의 폴리라인 모양이 곡선에 더 가깝습니다. 자세한 내용은 대략적인 다각형을 참조하십시오.
  • 닫힘: True 또는 False . True는 근사 곡선이 닫혀 있음을 나타내고 (첫 번째 정점이 마지막 정점에 연결됨), False는 근사 곡선이 닫히지 않음 을 나타냅니다.

        cv2.approxPolyDP는 대략적인 다각형의 꼭짓점 좌표를 반환합니다 . 여기서 엡실론 정밀도는 범위 내의 값으로 순회합니다 . 반환되는 꼭지점 좌표 의 수가 4 일 때 사변형 입니다 .

        각 윤곽선에 대해 사변형 피팅을 수행하고 cv2.polylinescv2.circle을 사용하여 가장자리정점을 각각 그립니다 . 효과는 다음과 같습니다.

        사각형이 맞춰진 후 각 사각형의 정점이 정렬 됩니다 .

원근 교정

# 透视矫正目标区域
w, h = 900, 300
rect = [point1[0], point1[-1], point2[-1], point2[0]]  # 顺序为第一个四边形的左上,第四个四边形的右上,第四个四边形的右下,第一个四边形的左下
pts1 = np.array(rect, dtype="float32")
pts2 = np.array([rect[0], [rect[0][0] + w, rect[0][1]],
                [rect[0][0] + w, rect[0][1] + h], [rect[0][0], rect[0][1] + h]], dtype="float32")
M = cv2.getPerspectiveTransform(pts1, pts2)  # 变换矩阵
img_warped = cv2.warpPerspective(img, M, (1500, 500))  # 透视变换

원근 변환cv2.warpPerspective를 사용          하기 전에 변환 행렬을 cv2.getPerspectiveTransform 으로 가져와야 합니다 .

        cv2.getPerspectiveTransform(src, dst)의 공통 매개변수는 다음과 같습니다.

  • src: 변환 전 사변형 이미지 꼭지점 좌표 ( 배열 ) . 여기서 세 점은 동일 선상에 있지 않습니다.
  • dst: 변환된 이미지 사변형꼭짓점 좌표 ( 배열 ) , 여기서 임의의 세 점이 동일선상에 있지 않음

        여기에 변환 전 사변형의 정점 좌표인 첫 번째 사변형의 왼쪽 위 좌표 , 네 번째 사변형의 오른쪽 위 좌표 , 네 번째 사변형의 오른쪽 아래 좌표 , 첫 번째 사변형 의 왼쪽 아래 좌표를 입력합니다. 사변형; 변환된 사변형의 정점 입력 좌표는 첫 번째 사변형의 왼쪽 위 좌표의 너비와 높이를 확장합니다 .

         cv2.getPerspectiveTransform(src, M, dsize)의 공통 매개변수 는 다음과 같습니다.

  • src: 입력 이미지
  • M: 변환 행렬
  • dsize: 출력 이미지 크기

         변환 효과는 다음과 같습니다.

img_warped = img_warped[rect[0][1]: rect[0][1] + h, rect[0][0]: rect[0][0] + w]  # 抠出变换后的区域

         변환된 영역을 잘라내면 효과는 다음과 같습니다.

참조 링크

RGB, HSV 및 HSL 색 공간을 빠르게 배울 수 있는 3분 - Programmer Sought

Chapter 8 형태론적 연산 -- 8.3 커널 함수 cv2.getStruturingElement()

Python +OpenCV CH9: 형태학 연산(morphologyEx 확장자)_liguoxin1990's blog-CSDN 블로그

Python OpenCV approxPolyDP() 함수

다각형 근사 cv2.approxPolyDP 및 Douglas-Peucker algorithm_00000cj's blog-CSDN blog_Polygon 근사 알고리즘

추천

출처blog.csdn.net/weixin_41611054/article/details/127456711