質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

1回答

4770閲覧

Python版のopencvを使った、リアルタイムでのキャリブレーションおよび、ひずみ補正。

mosu

総合スコア15

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

1クリップ

投稿2019/02/05 08:13

編集2019/02/13 08:04

前提・実現したいこと

Python版のopencvを使った、リアルタイムでのキャリブレーションおよび、ひずみ補正。

プログラミング初心者です。
Python版のopencvを使って、魚眼ウェブカメラ(画角150°)のキャリブレーションおよび、ひずみ補正をしたのですが、画像のように変にひずみ補正が行われ解決策を探しています。
本来は画像の真ん中の茶色い部分を主に補正したいと考えています。
右が補正前左が補正後です。
右が補正前、左が補正後です。

発生している問題・エラーメッセージ

なし

該当のソースコード

python

1コード

import cv2
import numpy as np
import os
import glob
import sys
assert float(cv2.version.rsplit('.', 1)[0]) >= 3, 'OpenCV version 3 or newer required.'

CHECKERBOARD = (7,10)
subpix_criteria = (cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1)
calibration_flags=cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC+cv2.fisheye.CALIB_CHECK_COND+cv2.fisheye.CALIB_FIX_SKEW
objp = np.zeros((1, CHECKERBOARD[0]CHECKERBOARD[1], 3), np.float32)
objp[0,:,:2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2)
_img_shape = None
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
images = glob.glob(r'C:\Users\Gen\Pictures\Camera Roll
jpg')#ここにキャリブレーションしたいフォルダ名を入力
for fname in images:
[ ]img = cv2.imread(fname)
[ ]if _img_shape == None:
[ ]_img_shape = img.shape[:2]
[ ]else:
[ ]assert _img_shape == img.shape[:2], "All images must share the same size."
[ ]gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

[ ]ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH+cv2.CALIB_CB_FAST_CHECK+cv2.CALIB_CB_NORMALIZE_IMAGE) [ ]if ret == True: [ ]objpoints.append(objp) [ ]cv2.cornerSubPix(gray,corners,(3,3),(-1,-1),subpix_criteria) [ ]imgpoints.append(corners)

N_OK = len(objpoints)
K = np.zeros((3, 3))
D = np.zeros((4, 1))
rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]
tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]
rms, _, _, _, _ =
cv2.fisheye.calibrate(
objpoints,
imgpoints,
gray.shape[::-1],
K,
D,
rvecs,
tvecs,
calibration_flags,
(cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-6)
)
print("Found " + str(N_OK) + " valid images for calibration")
print("DIM=" + str(_img_shape[::-1]))
print("K=np.array(" + str(K.tolist()) + ")")
print("D=np.array(" + str(D.tolist()) + ")")
以下3つにprintされたパラメーターを代入
DIM=(_img_shape[::-1])
K=np.array(K.tolist())
D=np.array(D.tolist())

balance=0.95

dim2=None

dim3=None

cap = cv2.VideoCapture(0)

fourcc = cv2.VideoWriter_fourcc(*'DIVX')

out = cv2.VideoWriter('output.avi',fourcc, 20.0, (1280,720))

out1 = cv2.VideoWriter('undistortedop.avi',fourcc, 20.0, (1280,720))

while True:

[ ]ret, frame = cap.read()

[ ]gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

[ ]dim1=(1280,720)

[ ]assert dim1[0]/dim1[1] == DIM[0]/DIM[1],
[ ]if not dim2:

[ ]dim2 = dim1

[ ]if not dim3:

[ ]dim3 = dim1

[ ]dim3=(1280,720)

[ ]scaled_K = K * dim1[0] / DIM[0] # The values of K is to scale with image dimension.

[ ]scaled_K[2][2] = 1.0 # Except that K[2][2] is always 1.0

[ ]new_K = cv2.fisheye.estimateNewCameraMatrixForUndistortRectify(scaled_K, D, dim2, np.eye(3), balance=balance)

[ ]map1, map2 = cv2.fisheye.initUndistortRectifyMap(scaled_K,D,np.eye(3),new_K,dim3, cv2.CV_16SC2)

[ ]undistorted_img = cv2.remap(frame, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)

[ ]out1.write(undistorted_img)

[ ]cv2.imshow("undistorted", undistorted_img)

[ ]out.write(frame)

[ ]cv2.imshow('frame',frame)

[ ]if cv2.waitKey(1) & 0xFF == ord('q'):

[ ]break

cap.release()

out.release()

out1.release()

cv2.destroyAllWindows()

試したこと

キャリブレーション用画像の取り直し。
異なった照明状況での撮影。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yohhoy

2019/02/06 07:28

(まずはPythonコードを整形ください https://teratail.com/help/question-tips#questionTips3-7 )チェッカーボード・キャリブレーション画像は何枚用意しましたか?またチェッカーボード位置は撮影画面内で移動させているでしょうか?
mosu

2019/02/07 13:27

チェッカーボード画像は15枚程度です。 移動はさせています。
guest

回答1

0

キャリブレーションが悪いのか,それとも後段の歪補正が悪いのか,の切り分けができているのでしょうか?

もしできていないなら,まずはキャリブレーション処理がまともにできているのかを確認してみてはどうでしょうか.

  • そもそも入力データたるfindChessboardCornersによる検出結果が全ての画像でまともなのか?
  • キャリブレーション結果のパラメータ値は(判断がつく範囲で)まともな値が得られているのか?
  • 特徴点の再投影誤差がとんでもなくでかい値とかになっていないのか?

など.

投稿2019/02/06 07:08

fana

総合スコア11658

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mosu

2019/02/07 13:26

ご回答ありがとうございます。 そこについても書いておくべきでした。ご指摘ありがとうございます。 ・そもそも入力データたるfindChessboardCornersによる検出結果が全ての画像でまともなのか? これは問題ないと思われます。プログラムを使ってコーナーが検出されていることが確認できました。 ・キャリブレーション結果のパラメータ値は(判断がつく範囲で)まともな値が得られているのか? 画像を用いたキャリブレーションおよびひずみ補正はうまくいっているのでこれもおそらく問題ないと思われます。 ・特徴点の再投影誤差がとんでもなくでかい値とかになっていないのか? これがわかりません。どこに相当するものでしょうか?
fana

2019/02/08 01:42 編集

> 画像を用いたキャリブレーションおよびひずみ補正はうまくいっているので 質問文に「変にひずみ補正が行われ…」と書かれていることと矛盾しているような…? 得られた内部パラメータの値そのものを見て,「明らかにおかしい値」かどうかの確認はされていますか? 例えば光軸点座標は,撮影画像を見れば「だいたいこの範囲にあるだろ」と検討が付くと思いますが,校正結果得られた値がそこから大きく外れた場所になっていたりしませんか? あるいは像高カーブをグラフとして描画してみたら,本来のカメラ画角と画像の解像度との関係をまともに表すものとして「不自然」ということはありませんか? > これがわかりません。どこに相当するものでしょうか? とりあえず自身で計算すればよいです. パターン上の特徴点の(パターン平面上での)座標は既知であり,パターン平面の外部パラメータは推定されているので,各特徴点のカメラ座標系における座標が計算できるハズです. カメラ座標系の位置がわかれば,推定された内部パラメータを用いて,それが撮影画像上のどこに写るのかを計算できます. この計算結果位置は,理想的には,撮影画像上でのその特徴点の検出座標と一致するハズですよね? しかし厳密にはまず一致しないので,その座標の差(再投影誤差)を見ます. これを全てのパターン画像の全ての特徴点について確認したとき,差が異常に大きいものが存在するようであれば,何かがうまくいっていません.
fana

2019/02/08 01:46

> findChessboardCornersによる検出結果 念のため: 特徴点検出結果は,チェスパターンを撮影した画像の上に(できれば数倍に拡大した解像度の上で)プロットしてみて, 全ての画像に関して目を皿のようにして確認しないとダメですよ. (経験上,OpenCVのこの関数の結果は,歪の大きいカメラ画像に対してはそれなりの頻度でダメです.)
mosu

2019/02/09 04:50

ご丁寧な回答ありがとうございます。 ・画像でのキャリブレーション...矛盾... については、目的のプログラムはウェブカメラで取得した映像に対しキャリブレーションおよびひずみ補正を行いたいと考えているのですが、画像に対しては取得したパラメーターで目的の場所がひずみ補正されているのですが、映像に対してひずみ補正となると画像で上げたような結果になってしまいここで質問をさせていただきました。 プログラムに問題があると考えたほうが自然でしょうか。 ・とりあえず自身で計算すればよいです. こういったことで確かめればよいということを知りませんでした。 ありがとうございます。計算し確かめてみます。 ・findChessboardCornersによる検出結果 これももう一度しっかりと見直します。 ありがとうございます。
fana

2019/02/09 08:15

> 画像に対しては取得したパラメーターで目的の場所がひずみ補正されているのですが、映像に対してひずみ補正となると... 「画像」と「映像」との間にどんな違いがあるのでしょうか? (チェスパターンを撮影したのと同じカメラの「映像」なんですよね?) > プログラムに問題があると考えたほうが自然でしょうか。 すでに修正依頼が成されていますが,コードを整形するとpythonがわかる人からの回答を得られやすくなるのではないでしょうか.
mosu

2019/02/13 08:01

>「画像」と「映像」との間にどんな違いがあるのでしょうか?   プログラムが違います。 私自身も疑問なのですが同じ場所で、同じカメラで撮影し取得したパラメーターなのでひずみ補正も同様にできるはずなのですができなかったので質問させていただきました。 >すでに修正依頼が成されていますが... わかりました。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問