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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

8376閲覧

アフィン変換した後の座標が知りたいc++

ag_ns_gt

総合スコア15

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/11/12 11:06

例えばアフィン変換する前の座標が点a(150,150)だったとすると、アフィン変換をした後、点aはどこの座標に移動してしまったのか知りたいと思っています。
pythonでの方法は見つけることができたのですがc++の方法が見つからなかったためわからないなりにpythonのプログラムを書き換えてみました。
アフィン変換自体は3点を指定してその3点を特定の3点に移動させる方法をとっています。

python

1import cv2 2 import numpy as np 3 im = cv2.imread('squares.jpg') 4 points1 = [[50,50],[150,50],[50,150]] 5 points2 = [[75,75],[150,50],[50,150]] 6 M = cv2.getAffineTransform(np.float32(points1), np.float32(points2)) 7 im2 = cv2.warpAffine(im, M, (200,200)) 8 cv2.imwrite('transformed_squares.jpg', im2) 9point = np.float32((150,150)) 10 x = point[0] 11 y = point[1] 12 new_x = M[0][0]*x + M[0][1]*y + np.float32(M[0][2]) 13 new_y = M[1][0]*x + M[1][1]*y + np.float32(M[1][2]) 14 print (int(new_x), int(new_y))

c++

1int main(int argc, char *argv[]) 2{ 3 Mat src_img = imread(imagename); 4 if (!src_img.data) 5 return -1; 6 const Point2f src_pt[] = { Point2f(a[0], b[0]), Point2f(a[1], b[1]), Point2f(a[47], b[47]) }; 7 const cv::Point2f dst_pt[] = { cv::Point2f(167, 207), cv::Point2f(327, 207), cv::Point2f(251, 485) }; 8 const Mat affine_matrix = getAffineTransform(src_pt, dst_pt); 9 Mat dst_img; 10 warpAffine(src_img, dst_img, affine_matrix, src_img.size()); 11 imwrite("dst.jpg", dst_img); 12 int point[] = { 150,150}; 13 int x = point[0]; 14 int y = point[1]; 15 int new_x = affine_matrix[0][0] * x + affine_matrix[0][1] * y + affine_matrix[0][2]; 16 int new_y = affine_matrix[1][0] * x + affine_matrix[1][1] * y + affine_matrix[1][2]; 17 printf("%d,%d",new_x, new_y); 18} 19

pythonのプログラムをc++で書き換えてみた結果affine_matrix[0][0]のところで
「(int) 0
これらのオペランドと一致する演算子[]はありません。
オペランドの型const cv::Mat[int]」
と出てしまいます。
pythonからc++に書き換えること自体初めてなので全然わかりません。
なぜこのような文がでてしまうのか教えていただきたいです。

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

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

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

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

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

guest

回答2

0

ベストアンサー

エラーの原因

pythonのプログラムをc++で書き換えてみた結果affine_matrix[0][0]のところで

「(int) 0 これらのオペランドと一致する演算子[]はありません。

オペランドの型const cv::Mat[int]」と出てしまいます。

cv::Mat クラスには operator[] の演算子オーバーロードは存在しないというエラーです。
cv::Mat クラスの (row, col) 成分にアクセスしたい場合は、cv::Mat::at<T>(row, col) 関数を使用します。
テンプレート引数 T は cv::Mat の各要素の型を指定してください。誤った型 (例えば、CV_64F 型の cv::Mat なのに float を指定した) 場合は、コンパイルエラーは起きませんが、正しく値を取得できません。
今回、cv::getAffineTransform() が返す cv::Mat は CV_64F なので、double になります。

ある点にアフィン変換を適用する場合

以下の2つのやり方があるかと思います。

M: 2x3 のアフィン変換行列

  • M[:, :2] * (x, y)^T + M[:, 2] と平行移動成分を分けて計算する。
  • M * (x, y, 1)^T と同次座標系に変数して計算する。

なので、cv::Mat の関数を使って、上の式をコード化してもよいのですが、OpenCV には点の一覧に対して行列演算を適用する cv::transform() という関数があります。
これを使うと、cv::transform(変換前の点一覧、変換後の点一覧、行列) と引数に指定することで、変換後の点を計算できます。
点は、std::vector<cv::Point_<T>> 型を要求するので、一点しか変換しない場合でも、要素1の配列としてください。

サンプルコード

cpp

1#include <iostream> 2#include <opencv2/opencv.hpp> 3 4int main() 5{ 6 std::vector<cv::Point2f> points1 = {{50, 50}, {150, 50}, {50, 150}}; 7 std::vector<cv::Point2f> points2 = {{75, 75}, {150, 50}, {50, 150}}; 8 9 cv::Mat M = cv::getAffineTransform(points1, points2); 10 std::cout << M << std::endl; 11 12 // 例えば、M_{11} 成分を取得したい場合 13 std::cout << M.at<double>(0, 0) << std::endl; 14 15 std::vector<cv::Point2f> points = {{150, 150}}; 16 cv::transform(points, points, M); 17 18 for (const cv::Point2f &p : points) 19 std::cout << p << std::endl; 20} 21 22

投稿2018/11/12 11:43

tiitoi

総合スコア21956

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

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

ag_ns_gt

2018/11/13 09:23

出来ました! 説明もわかりやすすぎるし、サンプルコードまで用意してくださって本当にありがたいです! お手数おかけしました。 ありがとうございました!
guest

0

プログラム読んでいませんけど一言。移動先を先に決めてからプログラムを作るわけであってプログラムを読み解いて移動先を調べるのは不自然です、目的と手段が逆です。

また、PythonとC++で結果が変わるなら書き換えがそもそもできていないことを意味します。目的が不明瞭です。

投稿2018/11/12 11:48

HogeAnimalLover

総合スコア4830

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

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

ag_ns_gt

2018/11/13 09:25

すいません。 私の知識不足でした。 もっと勉強します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問