高橋かずひとのプログラミング、その他、備忘録。

日々調べてたことや、作ってみたものをメモしているブログ。 お決まりの断り文句ですが、このブログに書かれている内容は個人の見解であり、所属する組織の公式見解ではありません。チラ裏。

【Windows】【Python】 OpenCVで魚眼レンズのカメラキャリブレーション

最近Pythonのコードの書きやすさに魅力を感じて、結構Pythonでサンプルプログラムとか書いてます。

で、表題の件。
この先仕事で魚眼とか超広角レンズを利用するかもしれないので、お試しサンプルを作ろうとしたら、
C++OpenCVに存在する cv::fisheye系のI/FがPython版には無いらしい。。。

しかたなく、色々諦めきれなかったので、Pythonで通常のキャリブレーションの手番を踏んで、
魚眼レンズをキャリブレーションしてみました。
Python版で出来たら、C++版でちゃんとした実装すれば技術的には問題無いでしょう理論

あれ?なんか普通に出来てる? 理由要確認。
あと、気持ち切り取られている箇所多いような気がしないでもない。
たぶん広角130度くらい確保出来ている。

ちなみに使用したカメラは以下↓
https://www.amazon.co.jp/ELP-USB2-0-Ominivison-OV2710-%E5%BA%A6%E3%83%A1%E3%82%AC%E3%83%94%E3%82%AF%E3%82%BB%E3%83%AB%E9%AD%9A%E7%9C%BC%E3%83%AC%E3%83%B3%E3%82%BA/dp/B017R02JLI
f:id:Kazuhito00:20160922210510j:plain

コードも以下に貼り付け↓

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import numpy as np
import cv2
import Tkinter
import tkMessageBox

square_side_length = 23.0 # チェスボード内の正方形の1辺のサイズ(mm)
grid_intersection_size = (10, 7) # チェスボード内の格子数

pattern_points = np.zeros( (np.prod(grid_intersection_size), 3), np.float32 )
pattern_points[:,:2] = np.indices(grid_intersection_size).T.reshape(-1, 2)
pattern_points *= square_side_length
object_points = []
image_points = []

root = Tkinter.Tk()
root.withdraw()

video_input = cv2.VideoCapture(1)
if (video_input.isOpened() == False):
    exit()

camera_mat, dist_coef = [], []

if tkMessageBox.askyesno('askyesno','キャリブレーションデータ(K.csv, d.csv)を読み込みますか?'):
    # キャリブレーションデータの読み込み
    camera_mat = np.loadtxt('K.csv', delimiter=',')
    dist_coef = np.loadtxt('d.csv', delimiter=',')
    print "K = \n", camera_mat
    print "d = ", dist_coef.ravel()
else:
    # チェスボードの撮影
    capture_count = 0
    while(True):
        ret, frame = video_input.read()

        # チェスボード検出用にグレースケール画像へ変換
        #grayscale_image = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)

        # チェスボードのコーナーを検出
        #found, corner = cv2.findChessboardCorners(grayscale_image, grid_intersection_size)
        found, corner = cv2.findChessboardCorners(frame, grid_intersection_size)

        if found == True:
            print 'findChessboardCorners : True'

            # 現在のOpenCVではfindChessboardCorners()内で、cornerSubPix()相当の処理が実施されている?要確認
            #term = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1)
            #cv2.cornerSubPix(grayscale_image, corner, (5,5), (-1,-1), term)
            #cv2.drawChessboardCorners(grayscale_image, grid_intersection_size, corner, found)

            cv2.drawChessboardCorners(frame, grid_intersection_size, corner, found)
        if found == False:
            print 'findChessboardCorners : False'

        cv2.putText(frame, "Enter:Capture Chessboard(" + str(capture_count) + ")", (100, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0,0,255), 1)
        cv2.putText(frame, "N    :Completes Calibration Photographing", (100, 75), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0,0,255), 1)
        cv2.putText(frame, "ESC  :terminate program", (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0,0,255), 1)
        #cv2.putText(grayscale_image, "Enter:Capture Chessboard(" + str(capture_count) + ")", (100, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0,0,255), 1)
        #cv2.putText(grayscale_image, "ESC  :Completes Calibration Photographing.", (100, 75), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0,0,255), 1)
        cv2.imshow('original', frame)
        #cv2.imshow('findChessboardCorners', grayscale_image)

        c = cv2.waitKey(50) & 0xFF
        if c == 13 and found == True: # Enter
            # チェスボードコーナー検出情報を追加
            image_points.append(corner)
            object_points.append(pattern_points)
            capture_count += 1
        if c == 110: # N
            if tkMessageBox.askyesno('askyesno','チェスボード撮影を終了し、カメラ内部パラメータを求めますか?'):
                cv2.destroyAllWindows()
                break
        if c == 27: # ESC
            if tkMessageBox.askyesno('askyesno','プログラムを終了しますか?'):
                video_input.release()
                cv2.destroyAllWindows()
                exit()

    if len(image_points) > 0:
        # カメラ内部パラメータを計算
        print 'calibrateCamera() start'
        rms, K, d, r, t = cv2.calibrateCamera(object_points,image_points,(frame.shape[1],frame.shape[0]),None,None)
        print "RMS = ", rms
        print "K = \n", K
        print "d = ", d.ravel()
        np.savetxt("K.csv", K, delimiter =',',fmt="%0.14f") #カメラ行列の保存
        np.savetxt("d.csv", d, delimiter =',',fmt="%0.14f") #歪み係数の保存

        camera_mat = K
        dist_coef = d

        # 再投影誤差による評価
        mean_error = 0
        for i in xrange(len(object_points)):
            image_points2, _ = cv2.projectPoints(object_points[i], r[i], t[i], camera_mat, dist_coef)
            error = cv2.norm(image_points[i], image_points2, cv2.NORM_L2) / len(image_points2)
            mean_error += error
        print "total error: ", mean_error/len(object_points) # 0に近い値が望ましい(魚眼レンズの評価には不適?)
    else:
        print "findChessboardCorners() not be successful once"

# 歪み補正画像表示
if camera_mat != []:
    while(True):
        ret, frame = video_input.read()
        undistort_image = cv2.undistort(frame, camera_mat, dist_coef)

        cv2.imshow('original', frame)
        cv2.imshow('undistort', undistort_image)
        c = cv2.waitKey(50) & 0xFF
        if c==27: # ESC
            break

video_input.release()
cv2.destroyAllWindows()

以上。

【Windows】テキストエディタATOMでPlantUML

長らくサクラエディタを利用していたのですが、最近ATOMと言うエディタをちょくちょく触っています。
色々プラグインでカスタマイズすると便利らしい。

今日はPlantUMLを記述したかったので、「plantuml-viewer」をインストールして試してみた↓
結構さくさく書けそうで今後UMLを記述するのに利用していきたい。

f:id:Kazuhito00:20160922202824p:plain

ちょくちょくインストール手順を忘れるのでメモ↓
① Chocolatey(Windows用パッケージ管理ソフト)をインストール
 ①-1.管理者権限でコマンドプロンプトを起動
 ①-2.以下コマンドを実行し、Chocolateyをインストール
    「@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex (new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin」

②ライブラリインストール
 JavaレンダリングライブラリのGraphvizが必要になるためインストールする
 ②-1.「cinst jdk8 -y」
 ②-2.「cinst graphviz -y」

③-1.ATOM設定
 AtomでPlantUMLのプレビューするためにPlantUML Viewerをインストールする
③-2.ATOMのinstallから「plantuml-viewer」をインストール
 ③-2-1.SettingsにCharsetという項目があるので、ここにUTF-8を設定する
③-3.ATOMのinstallから「language-plantuml」をインストール

メモのメモ。

ブログにまとめておきたいことのメモ。
今からやろうとしているものは良いが、すでにやってしまった後のものが
いつまでもブログに載らない予感。。。

・【WindowsPython(Anaconda利用)でのOpenCV環境構築

  ⇒Qiitaとかググったら出てくるので保留。
・【WindowsVisual Studio 2015 CommunityでのOpenCV環境構築(拡張モジュール群 (opencv_contrib)込み)

  ⇒Qiitaとかググったら出てくるので保留。

・【WindowsAndroid Studio にOpenCV3.1をインストールする
・【Windows】Droid CAMを利用してAndroid端末をWebカメラ化し、OpenCVで画像処理
・【WindowsOpenCVを用いてステレオマッチング(SGBM法)
・【WindowsOpenCVを用いて透視変換
・【WindowsOpenCVを用いて背景差分取得(MoG法、KNN法)
・【WindowsOpenCVを用いてラベリング
・【WindowsOpenCVを用いて魚眼Webカメラキャリブレーション
       +DroidCamセルカレンズのキャリブレーション
・【Windows】OpenCV3.1拡張モジュールのTrackingAPIを動作確認
・【Windows】Parrot社ドローン「Airborne Cargo」をSDKから操作
・【Windows】ycapture を用いてOpenCV 処理結果を Windows のビデオソースとして扱う

・【Linux】gstreamer, v4l2lloopback

WindowsAtomでplantUMLを記述する環境を構築

・【Windows】TORCS(The Open Racing Car Simulator)

・【Linux】【ROS】Autoware

テスト投稿

日々調べてたことや、作ってみたものをメモしていける場が

欲しいと思い、ブログを開設。

ひとまずは、メモを投稿していくイメージで、

ちゃんとまとめたものはQiitaにあげていきたい。