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

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

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

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

C++

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

Q&A

解決済

3回答

2217閲覧

opencvによる画像のせん断変形

tkphone343

総合スコア6

OpenCV

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

C++

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

0グッド

0クリップ

投稿2021/12/06 03:46

opencvを使って、読み込んだ画像の中心を変形の中心としたせん断変形を行うプログラムを作成したいのですが、自分が調べた限りではわかりませんでした。
opencvを使うのは初めてなので関数等もあまり把握できていませんが、考え方だけでもいいのでご教授願いたいです。

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

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

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

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

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

jbpb0

2021/12/06 08:08

https://note.nkmk.me/python-opencv-warp-affine-perspective/ の「任意の変換行列を定義」の、「スキューの例は以下の通り。」と書かれてるところの下に、コード例が二つあります 画像を読み込んだ後に上記コード例をそのまま実行したら、そこに掲載されてる処理後の画像を見ても分かるように、処理後の画像が全てはみ出さないように、元画像よりも大きなサイズの画像ができます その処理後の画像の真ん中から、元画像と同じサイズの部分を切り出したら、 > 読み込んだ画像の中心を変形の中心としたせん断変形 になると思います
guest

回答3

0

まずは「アフィン変換 OpenCV」とかで検索してみては.


OpenCVの関数名を記しておきます.

  • getAffineTransform : 3点の対応から 2x3 の変換マトリクスが得られます.
  • warpAffine : 2x3 の変換マトリクスを用いて画像を変換します.

[追記]
とりあえず,ある座標の位置が変わらないような変形をするコードを書いてみました.
参考になれば.

C++

1int main() 2{ 3 const cv::Point TopLeft( 105, 55 ); 4 const cv::Point BottomRight( 256, 178 ); 5 const cv::Point Center = ( TopLeft + BottomRight ) * 0.5; //※変換の中心 6 7 cv::Mat Img( 240, 320 ,CV_8UC3 ); 8 {//※元画像に,何かてきとーに「中心」がわかるような描画 9 Img = cv::Scalar( 96, 0, 0 ); 10 cv::rectangle( Img, TopLeft, BottomRight, cv::Scalar(0,0,255) ); 11 12 const cv::Point TopRight( BottomRight.x, TopLeft.y ); 13 const cv::Point BottomLeft( TopLeft.x, BottomRight.y ); 14 cv::line( Img, TopLeft, BottomRight, cv::Scalar(0,0,255) ); 15 cv::line( Img, BottomLeft, TopRight, cv::Scalar(0,0,255) ); 16 17 cv::circle( Img, Center, 6, cv::Scalar( 0,255,255 ), 1 ); 18 cv::circle( Img, Center, 40, cv::Scalar( 0,255,0 ), 3 ); 19 } 20 cv::imshow( "Img", Img ); 21 22 //変換マトリクスを作る 23 cv::Matx<float,2,3> M = 0; 24 { 25 //てきとーに「せん断」になる感じの値 26 M(0,0) = 1; M(1,1)=1; //左側2x2部分対角は1 27 M(0,1) = 0.25; //せん断の成分(1) 28 M(1,0) = 0.5; //せん断の成分(2) 29 //Centerの位置が変わらないような並進成分を求めてマトリクスにセット 30 cv::Vec2f TransedCenter = M * cv::Vec3f( (float)Center.x, (float)Center.y, 1.0f ); 31 M(0,2) = ( Center.x - TransedCenter(0) ); 32 M(1,2) = ( Center.y - TransedCenter(1) ); 33 } 34 35 //マトリクスMでアフィン変換 36 cv::Mat ResultImg; 37 cv::warpAffine( Img, ResultImg, M, cv::Size(Img.cols, Img.rows) ); 38 cv::imshow( "Affine", ResultImg ); 39 40 //元画像と重ねて表示してみる 41 cv::addWeighted( Img, 0.5, ResultImg, 0.5, 0, ResultImg ); 42 cv::imshow( "Result", ResultImg ); 43 44 // 45 if( cv::waitKey() == 's' ) 46 { 47 cv::imwrite( "Img.png", Img ); 48 cv::imwrite( "Result.png", ResultImg ); 49 } 50 return 0; 51}

変換前の画像 Img の表示結果:
(「ある座標」の位置がわかるような適当な図形が描画されている)
イメージ説明

アフィン変換結果と変換前画像を重ねてみた表示結果:
(描画した図形の真ん中が一致している)
イメージ説明

※上記コードの //Centerの位置が変わらないような並進成分を求めてマトリクスにセット のところを,(このマトリクスの内容を前提として)手計算した結果で書くならば,

C++

1M(0,2) = -Center.y * M(0,1); 2M(1,2) = -Center.x * M(1,0);

となりますが,汎用性を考えれば(?) 上記コードのように「中心」を変換した座標から並進量を求めるので良いかと(そこに圧倒的な計算時間を要するとかいうこともないでしょうから).

投稿2021/12/06 04:05

編集2021/12/07 07:20
fana

総合スコア11996

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

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

tkphone343

2021/12/06 04:14

アフィン変換は参考にしている本にも記載されていたので一通り目を通したつもりですが、画像の中心を回転の中心にする関数はあったものの、せん断変形ではなさそうで困っています。 アフィン変換で平行移動などして、自分で画像の中心を持ってくるしかないのでしょうか。
fana

2021/12/06 04:17

せん断 は アフィン変換 で扱える変形のひとつです.
tkphone343

2021/12/06 04:24

認識と言葉が足らず申し訳ありません。 関数warpAffineで画像のアフィン変換が行える、その中の変換行列の値によってせん断等の線形変換が行える、という認識でいますがあっていますでしょうか。
fana

2021/12/06 04:28

> その中の変換行列の値によってせん断等の線形変換が行える そうですね. 変換行列の中身を自前で計算するか,あるいは getAffineTransform とかを使う手があるでしょう.
fana

2021/12/07 07:00

getAffineTransform を使わないコードを追記してみました. ・とりあえず「せん断」変形をするためのマトリクスMを作り, ・そのMで座標変換したら「中心」がどこに行くかを計算し, ・「中心」がずれないようにMの並進変換の成分の値をセット という手順でマトリクスMを用意し,warpAffine に食わせています.
guest

0

自己解決

自分の理解不足で申し訳ございません。
出力画像にせん断変形した画像が収まるようにしたかったのですが、縮小や平行移動で解決できそうです。

みなさまからの回答は理解を深めるためゆっくりと読ませていただきます。
詳しい説明等ありがとうございました。

投稿2021/12/09 03:13

tkphone343

総合スコア6

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

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

0

「画像の中心を変形の中心としたせん断変形」という意味を理解できていないかもしれませんが、サンプルを書いてみました。

import numpy as np import cv2 from matplotlib import pyplot as plt #画像読み込み img = cv2.imread('./sample_data/input.jpg') h,w,_ = img.shape print(h,w) # 横方向に20画素分せん断させる場合 shear_x_pix = 20 # 元画像の変形前の座標を4か所指定 p_original = np.float32([ [0, 0], # 元画像の左上点 [w, 0], # 元画像の右上点 [0, h], # 元画像の左下点 [w, h]] # 元画像の右下点 ) # 元画像の上記4点を変形によってどの座標に移動させるのかを座標で指定(これも4点) p_trans = np.float32([ [shear_x_pix, 0], # 左上点の移動先 [w + shear_x_pix, 0], # 右上点の移動先 [0, h], # 左下点の移動先(このケースでは移動しない) [w, h]] # 右下点の移動先(このケースでは移動しない) ) # 変換マトリクスと射影変換 M = cv2.getPerspectiveTransform(p_original, p_trans) # 変形後の画像サイズ out_size = (w + shear_x_pix, h) out = cv2.warpPerspective(img, M, out_size) print(out.shape) plt.imshow(cv2.cvtColor(out, cv2.COLOR_BGR2RGB))

参考画像の幾何変換

投稿2021/12/06 08:28

taront

総合スコア59

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

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

fana

2021/12/06 09:14

> 「画像の中心を変形の中心としたせん断変形」という意味 私も推測しかできませんが,回転で言うところの回転中心みたいな,「その位置だけは動かない」的な場所を指しているように思います. (上辺を右にΔだけ動かすなら下辺は逆に左方向にΔだけ動かせば中央は動かない感,みたいな)
taront

2021/12/06 23:21

なるほど、だとすれば中心基準で移動先の4点を決めるか、変形後に平行移動が必要そうですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問