2017-11-20 75 views
0

OpenCV Pythonで構造化ライトを使用してプロジェクタとカメラからポイントを三角形分割しようとしています。このプロセスでは、カメラとプロジェクタの間に1対1で対応するタプルのリストがあります。私は()以下のようにcv2.undistortedPointsにこれを渡しています:camera_normalizedPoints = cv2.undistortPoints(camera_points, camera_K, camera_d)cv2.undistortPoints()のエラーを理解する助けが必要です

しかし、Pythonは、次のエラーを投げていると私はエラーが何を意味するかを理解することができません。

camera_normalizedPoints = cv2.undistortPoints(camera_points, camera_K, camera_d) cv2.error: /home/base/opencv_build/opencv/modules/imgproc/src/undistort.cpp:312: error: (-215) CV_IS_MAT(_src) && CV_IS_MAT(_dst) && (_src->rows == 1 || _src->cols == 1) && (_dst->rows == 1 || _dst->cols == 1) && _src->cols + _src->rows - 1 == _dst->rows + _dst->cols - 1 && (CV_MAT_TYPE(_src->type) == CV_32FC2 || CV_MAT_TYPE(_src->type) == CV_64FC2) && (CV_MAT_TYPE(_dst->type) == CV_32FC2 || CV_MAT_TYPE(_dst->type) == CV_64FC2) in function cvUndistortPoints

すべてのヘルプは大歓迎です。

ありがとうございました。

+1

あなたが渡しているもののようなものが正確に含まれている必要があります。PythonのOpenCVは、通常、* 2チャンネル*配列内のポイントを必要とし、それらを1チャンネル配列として渡していると思います。 '[[x1、y1]、[x2、y2]、...]'のようなリストのリストとしてのポイントの代わりに、それらは '[[[x1、y1]]、[[x2 、y2]]、...] 'である。また、ポイントが32ビットまたは64ビットの浮動小数点数であることを確認します。したがって、ポイント配列は 'np.array([[[x1、y1]]、[[x2、y2]]、...] 、dtype = np.float32) 'となります。それが解決すれば、私は答えとして書きます。 –

+0

@AlexanderReynolds - はい、ポイントを '[[x1、y1]、[x2、y2]、...]'として渡しています。あなたが提案したように、私は今、 '[[[x1、y1]]、[[x2(x1、y1)]の代わりに' camera_points = np.array [camera_points]、dtype = np.float32 ' 、y2]]、...] '[[[x1、y1]、[x2、y2]、...]]'を取得しています。私が確認できるように、それを正しく行う方法を教えてもらえますか? – Shubs

+0

軸を反転するだけで、これらのポイントを転置することができます。 'points = points.transpose(1,0,2)'はトリックを行うべきです(これは0と1の軸を反転させます)。 –

答えて

1

ドキュメントはPythonの入力シェイプについては明示的ではありませんが、undistortPoints()にはまだPythonのマニュアルがありません。

入力ポイントは、形状が(n_points, 1, n_dimensions)の配列である必要があります。したがって、2D座標の場合は、形状は(n_points, 1, 2)でなければなりません。または、3D座標の場合、形状は(n_points, 1, 3)でなければなりません。これは、の場合に最も多く、 OpenCV関数の場合に当てはまります。 AFAIKでは、この形式はすべて OpenCV関数で動作しますが、いくつかのOpenCV関数では形状が(n_points, n_dimensions)の点も受け入れます。私はすべてのものを一貫性のあるものにして、フォーマット(n_points, 1, n_dimensions)にするのが最善の方法だと思っています。

:あなたは np.newaxisとそれを拡張することができます (n_points, n_dimensions)形状を有する配列を持っている場合は

points = np.array([[[x1, y1]], [[x2, y2]], [[x3, y3]], [[x4, y4]]], dtype=np.float32) 

:これは4つの32ビット浮動小数点2Dポイントの配列は次のようになり意味明確にすることが

>>> points = np.array([[1, 2], [3, 4], [5, 6], [7, 8]]) 
>>> points.shape 
(4, 2) 
>>> points = points[:, np.newaxis, :] 
>>> points.shape 
(4, 1, 2) 

またはnp.expand_dims()と:

>>> points = np.array([[1, 2], [3, 4], [5, 6], [7, 8]]) 
>>> points.shape 
(4, 2) 
>>> points = np.expand_dims(points, 1) 
>>> points.shape 
(4, 1, 2) 

、またはnp.transpose()のさまざまな注文を使用して、寸法の順序に従います。例えば、形状が(1, n_points, n_dimensions)の場合は、軸0を軸1とスワップして(n_points, 1, n_dimensions)にする必要があります。したがって、points = np.transpose(points, (1, 0, 2))は、軸1を最初に、次に軸0を、軸2を軸に変更して、新しい形状が正しいようにします。


あなたは、これがポイントの奇妙なフォーマットだと思う場合は、画像の座標として点を考える場合にのみ、ポイントのリストが、合理的に考えるならば、それはあります。イメージを持っている場合は、画像の各点の座標は(x, y)ペアによって定義される、等:

(0, 0) (1, 0) (2, 0) ... 
(0, 1) (1, 1) (2, 1) ... 
(0, 2) (1, 2) (2, 2) ... 
... 

ここでは、2チャンネルのアレイの別個のチャネルにそれぞれを置く調整するために理にかなって、

チャネル0(x座標):あなたは、x座標の1つの2Dアレイなどy座標の1つの2Dアレイを取得するように

0 1 2 ... 
0 1 2 ... 
0 1 2 ... 
... 

チャネル1(y座標)。

0 0 0 ... 
1 1 1 ... 
2 2 2 ... 
... 

これが、それぞれの座標を別々のチャンネルに持つ理由です。


このフォーマットを必要とするいくつかの他のOpenCVの関数は、それぞれcv2.transform()cv2.perspectiveTransform()、私が前に約同じ質問に答えました、herehereが含まれます。