OpenCV3とPython3で形状のある物体の輪郭と方向を認識する(主成分分析:PCA、固有ベクトル)

OpenCV3とPython3で形状のある物体の輪郭と方向を認識する(主成分分析:PCA、固有ベクトル) こちらのコードを参考に動かしてみた。一か所修正で動いた。
コードの意味はまだよくわからないが、すごいな。
ラベルの外観検査の傾き検出に使えそうだ。
タイトル
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# -*- coding: utf-8 -*-
import cv2
import math
import numpy as np
 
 
# ベクトルを描画する
def drawAxis(img, start_pt, vec, colour, length):
    # アンチエイリアス
    CV_AA = 16
 
    # 終了点
    end_pt = (int(start_pt[0] + length * vec[0]), int(start_pt[1] + length * vec[1]))
 
    # 中心を描画
    cv2.circle(img, (int(start_pt[0]), int(start_pt[1])), 5, colour, 1)
 
    # 軸線を描画
    cv2.line(img, (int(start_pt[0]), int(start_pt[1])), end_pt, colour, 1, CV_AA);
 
    # 先端の矢印を描画
    angle = math.atan2(vec[1], vec[0])
    print(angle)
 
    qx0 = int(end_pt[0] - 9 * math.cos(angle + math.pi / 4));
    qy0 = int(end_pt[1] - 9 * math.sin(angle + math.pi / 4));
    cv2.line(img, end_pt, (qx0, qy0), colour, 1, CV_AA);
 
    qx1 = int(end_pt[0] - 9 * math.cos(angle - math.pi / 4));
    qy1 = int(end_pt[1] - 9 * math.sin(angle - math.pi / 4));
    cv2.line(img, end_pt, (qx1, qy1), colour, 1, CV_AA);
 
 
if __name__ == '__main__':
    # 画像を読み込む
    src = cv2.imread("pca_test1.jpg")
 
    # グレースケールに変換
    gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
 
    # 2値化
    retval, bw = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
 
    # 輪郭を抽出
    #   contours : [領域][Point No][0][x=0, y=1]
    #   cv2.CHAIN_APPROX_NONE: 中間点も保持する
    #   cv2.CHAIN_APPROX_SIMPLE: 中間点は保持しない
    #img, contours, hierarchy = cv2.findContours(bw, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
    contours, hierarchy = cv2.findContours(bw, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
 
    # 各輪郭に対する処理
    for i in range(0, len(contours)):
 
        # 輪郭の領域を計算
        area = cv2.contourArea(contours[i])
 
        # ノイズ(小さすぎる領域)と全体の輪郭(大きすぎる領域)を除外
        if area < 1e2 or 1e5 < area:
            continue
 
        # 輪郭を描画する
        cv2.drawContours(src, contours, i, (0, 0, 255), 2, 8, hierarchy, 0)
 
        # 輪郭データを浮動小数点型の配列に格納
        X = np.array(contours[i], dtype=np.float).reshape((contours[i].shape[0], contours[i].shape[2]))
 
        # PCA(1次元)
        mean, eigenvectors = cv2.PCACompute(X, mean=np.array([], dtype=np.float), maxComponents=1)
 
        # 主成分方向のベクトルを描画
        pt = (mean[0][0], mean[0][1])
        vec = (eigenvectors[0][0], eigenvectors[0][1])
        drawAxis(src, pt, vec, (255, 255, 0), 150)
 
 
    # 表示
    cv2.imshow('output', src)
    cv2.waitKey(0)
 
    # 終了処理
    cv2.destroyAllWindows()

実行結果

コメント

このブログの人気の投稿

Python OpenCVとWebカメラでバーコードリーダー

VB.net Dictionaryクラスの初期化