社会人研究者が色々頑張るブログ

pythonで画像処理やパターン認識をやっていきます

PythonとOpenCVで2点を通る直線を引く

やりたいこと

OpenCVのline関数は、ある2点を端点とする線分を引くことができます。(左図)
右図の様に、2点を通る直線を簡単に引く方法を示します。

こうじゃなくて こっちがやりたい
f:id:nsr_9:20210814225300p:plain f:id:nsr_9:20210814225306p:plain

コピペで動くコード

import cv2
import numpy as np


def linear(n1, n2):
    a = (n2[1]-n1[1])/(n2[0]-n1[0])
    b = (n2[0]*n1[1]-n1[0]*n2[1])/(n2[0]-n1[0])
    return a, b


def cross_point(n1, n2, m1, m2):
    a1, b1 = linear(n1, n2)
    a2, b2 = linear(m1, m2)

    if a1 == a2:
        return None, None
    return (b2-b1)/(a1-a2), (a1*b2-b1*a2)/(a1-a2)


def calc_straight(img, n1, n2):
    top = [[0, 0], [img.shape[1], 0]]
    btm = [[0, img.shape[0]], [img.shape[1], img.shape[0]]]

    tp = cross_point(n1, n2, top[0], top[1])
    bp = cross_point(n1, n2, btm[0], btm[1])

    tp = list(map(int, tp))
    bp = list(map(int, bp))
    print(tp[0], tp[1])

    return tp, bp


def test():
    img = np.zeros([512, 512, 3], dtype=np.uint8)

    n1 = np.random.randint(0, img.shape[0], [2])
    n2 = np.random.randint(0, img.shape[0], [2])

    tp, bp = calc_straight(img, n1, n2)

    cv2.circle(img, n1, 5, (255, 0, 0), -1)
    cv2.circle(img, n2, 5, (255, 0, 0), -1)

    cv2.line(img, (tp[0], tp[1]), (bp[0], bp[1]), (0, 0, 255), 1)

    return img

動作例

こんな感じで青い2点を通る直線を描画できます f:id:nsr_9:20210814233630g:plain

動作原理

動作原理はとてもシンプルです。
2点を通る直線と画像の上部(の横線)の交点Cと、画像の下部(の横線)の交点Dを求め、C−Dを通る直線を描画しています。
f:id:nsr_9:20210814234012p:plain