opencv で マーカー付き用紙の向きを直してみる

マーカーの検出を利用して、向きを直してみます。

カメラの歪み補正等(キャリブレーション)には踏み込みません。

四隅に黒い円のマーカーを付けた用紙です。

f:id:pongsuke:20170531161053j:plain

この傾きを補正しようと思います。

流れは

  1. マーカー検出

  2. 座標の並び替え

  3. 射影変換

#!/usr/bin/env python
# -*- coding: utf-8 -*
import cv2
import numpy as np

"""
円検出と、射影変換
"""
def main():
    image = cv2.imread('DSC_3009.jpg')
    #cv2.imshow('original', image)

    height, width ,depth    = image.shape
    # リサイズ
    image = cv2.resize(image, (width/4, height/4))
    imageOrg    = image.copy()
    height, width ,depth    = image.shape

    # グレースケールに変換
    image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # ガウシアンフィルタ
    image = cv2.GaussianBlur(image, (5, 5), 0)
    # 二値変換
    ret, image = cv2.threshold(image,127,255,cv2.THRESH_BINARY)

    # Python: cv2.findCirclesGridDefault(image, patternSize[, centers[, flags]]) → retval, centers
    # CALIB_CB_SYMMETRIC_GRID uses symmetric pattern of circles.
    # CALIB_CB_CLUSTERING uses a special algorithm for grid detection. It is more robust to perspective distortions but much more sensitive to background clutter.
    retval, centers = cv2.findCirclesGrid(image, (2,2), flags=cv2.CALIB_CB_SYMMETRIC_GRID + cv2.CALIB_CB_CLUSTERING)
    if retval:
        print centers
        image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
        image = cv2.drawChessboardCorners(image, (2,2), centers, retval)

    # 射影変換のために、並び替えた配列を用意する
    points  = np.array([
        centers[0],
        centers[2],
        centers[3],
        centers[1]
    ])
    print points

    # 外接矩形
    bRect = cv2.boundingRect(points)
    print bRect
    cv2.rectangle(image, (bRect[0], bRect[1]), (bRect[0]+bRect[2], bRect[1]+bRect[3]), (255,0,0), 2)
    cv2.imshow('drawChessboardCorners', image)
    cv2.imwrite('90.drawChessboardCorners.png', image)

    # 射影変換
    # 右上、左上、左下、右下
    pts1 = np.float32(points)
    pts2 = np.float32([
        [bRect[0]+bRect[2],bRect[1]],
        [bRect[0],bRect[1]],
        [bRect[0],bRect[1]+bRect[3]],
        [bRect[0]+bRect[2],bRect[1]+bRect[3]],
    ])
    print(pts1)
    print(pts2)
    M = cv2.getPerspectiveTransform(pts1,pts2)
    imageOrg = cv2.warpPerspective(imageOrg,M,(width,height))
    cv2.imshow('getPerspectiveTransform', imageOrg)
    cv2.imwrite('90.getPerspectiveTransform.png', imageOrg)

    cv2.waitKey(0)
    cv2.destroyAllWindows()
    return 0

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        pass

検出された円と、外接矩形
f:id:pongsuke:20170531161530p:plain

完了
f:id:pongsuke:20170531161558p:plain