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はSaturation(彩度、色純度、値:0~255)、VはValue(明るさ、値:0~255)、詳細表示:HSV色空間各色の値の範囲は次のとおりです。

には 2 つの値の範囲があり、これら 2 つの範囲はほとんどの場合補完的な関係にあり、実際の状況に応じて調整できることが         わかります。

# 颜色识别(红色),过滤红色区域
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.getStructuringElementによって定義する必要があります

        cv2.getStructuringElement(shape, ksize) の共通パラメータは次のとおりです。

  • 形状: カーネルの形状、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 (トップハット演算)、cv2.MORPH_BLACKHAT (ブラック ハット演算)、詳細を参照:形態素演算
  • カーネル:形態素演算用の畳み込みカーネル
  • 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 階層ツリー構造のアウトラインを構築する
  • 方法: 輪郭の近似方法
cv2.CHAIN_APPROX_NONE すべての輪郭点を保存し、隣接する 2 つの点間のピクセル位置の差が 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.estimatePolyDP(curve, epsilon, Closed)        を使用します。一般的なパラメータは次のとおりです。

  • 曲線:入力2 次元点セットの配列
  • ε:近似結果の精度これは、元の曲線とその近似曲線の間の最大距離です。イプシロンが小さいほど、近似結果のポリラインの形状は曲線に近づきます。詳細については、「近似ポリゴン」を参照してください。
  • 閉じた: TrueまたはFalseTrue は近似曲線が閉じている(最初の頂点が最後の頂点に接続されている) ことを示し、False は近似曲線が閉じていないことを示します

        cv2.estimatePolyDP は近似多角形の頂点座標を返します. ここで,イプシロン精度は 範囲内の値でトラバースされます. 返される頂点座標の数が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:変換前の画像四角形頂点座標(配列) (3 点が同一線上にない場合)
  • dst:変換されたイメージ四角形の頂点座標(配列) 。ここで、3 つの点は同一線上にありません。

        ここでは、変形前の四角形の頂点座標を入力します。1つ目の四角形の左上座標4つ目の四角形の右上座標4つ目の四角形の右下座標、 1つの四角形の左下座標です。四角形; 変形した四角形の頂点を入力 座標は、最初の四角形の左上の座標の幅と高さを拡張します。

         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]  # 抠出变换后的区域

         変換された領域を切り取ると、次のような効果が得られます。

参考リンク

3 分で RGB、HSV、HSL の色空間をすばやく学習 - プログラマーが求めた

第 8 章 形態素演算 -- 8.3 カーネル関数 cv2.getStructuringElement()

Python +OpenCV CH9: 形態素演算 (morphologyEx 拡張機能)_liguoxin1990 のブログ - CSDN ブログ

Python OpenCVのaboutPolyDP()関数

ポリゴン近似 cv2.estimatedPolyDP と Douglas-Peucker アルゴリズム_00000cj のブログ-CSDN ブログ_ポリゴン近似アルゴリズム

おすすめ

転載: blog.csdn.net/weixin_41611054/article/details/127456711