• ベストアンサー

画像回転について

いつもお世話になります。 下記ソースにてビットマップの回転を実現させようとしております。 ソースの一部ですので処理概要を説明すると、 まず、編集用画像領域をimage[][]に格納しておいて、 バッファでデータのやり取りをしており、下記ソースで演算後、 BitBltしております。 そこで、三角関数の処理に公式を利用しているのですが、 どうも左回転してしまいます。右回転したいので 安直に下記RotX・RotYを入れ替えたら右回転したんですけど、 実際の表示位置とは反転してしまいます。 数学的な話だと思うのですが、正常に右回転する方法を ご存知の方、ご教授よろしくお願い致します。 開発環境はVC++6.0MFCです。 for (y = 0 ; y<Height ; y++) { //オリジナル針のY方向  for (x=0 ; x<Width ; x++) { //オリジナル針のX方向   double IncreX=x-2.5;  //針中心からのベクトル   double IncreY=y-31.5; //針中心からのベクトル   double RotX= IncreX*::cos(m_dSAngle)-IncreY*::sin(m_dSAngle);   double RotY= IncreX*::sin(m_dSAngle)+IncreY*::cos(m_dSAngle);   long Offset = long(50.0+RotY) * 100 + long(50.0+RotX);   ASSERT(Offset<100*100);   *(buf+Offset)=image[y][x];  } }

質問者が選んだベストアンサー

  • ベストアンサー
  • g_dori
  • ベストアンサー率47% (330/699)
回答No.2

他のソースが見えないので何とも言えませんが、多分ここのところが問題なんだと思いますのでアドバイスさせて頂きます。 DIBでの画像データは左下がオフセットとなり、右方向へなめて一段上へ・・・このように格納されています。 これを理解せずに回転しようとすると、反対方向へ回転しますので、DIBをバイナリレベルで扱う場合は注意してください。 image[0][0]は画像左下の座標なので、y座標の考え方を根本から反転してください。表示位置に影響が出たのはそのためだと思われます。 *DDサーフェイスはちゃんと左上が頂点ですが、過去の解答を見る限りDIBですよね? また、オリジナル側の画像を参照して回転すると、斜線がガタガタになったり、画像に穴ができたりします。 根本的な対策は、ここで言うところのbuf側から全部の座標を埋めていく事です。 ※ここで複数の座標を参照すれば綺麗な中間色が出せます。が、重い・・・ ソースは御自身で作成できると思いますので、頑張ってください。このままでよろしければ、yのあたりをチョコッと直せば済む筈です。 *私はWin32ベース(というか、こういう細かい部分はasm)で作るので、MFCベースのソースはちょっと・・なので。投げやりでごめんなさい。 また、回転拡大縮小はAPIに任せた方が楽だと思いますよ? 結局キャッシュミスが起こるので、アセンブラで作成しても大差ないです。 尚、参照URLの方が的確なアドバイスが選られると思います。 ご参考まで。

参考URL:
http://www.bio100.co.jp/

その他の回答 (1)

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.1

角度の測り方は反時計回りが標準ですから、普通にやったのでは左回転 するでしょうね。 で、時計回りにするには、簡単です。角度をマイナスにすれば良いのです。 ご質問の例ではm_dsAngleを(-m_dsAngle)で入れ替えればよいことになります。

関連するQ&A

  • 回転行列の定義について

    回転行列の定義について 点P(x,y)を原点Oの周りに角θだけ回転させた点をP'(x',y')とすると (x')=(cosθ -sinθ)(x) (y')  (sinθ  cosθ)(y) ※上下2段で1つの行列と見てください と表せ,この (cosθ -sinθ) (sinθ   cosθ) を回転行列と呼ぶ。これは理解できるのですが          (x' y')=(x y)( cosθ sinθ)          (-sinθ cosθ) と考えることもできますよね。この (  cosθ sinθ) (-sinθ cosθ) を回転行列と呼ぶことはできないのでしょうか。 むしろ座標は横に並べて書く方が慣れているので、できればこちらで考えたいのですが…。 もしできるのであれば、実用的(試験等)にこちらの考え方を使うことはできるのでしょうか。 また、できないのであれば前者は○で後者が×となる理由があるのでしょうか。

  • 3次元の回転角度の求め方について教えてください。

    3次元の回転角度の求め方について教えてください。 3軸の加速度センサーがあります。 まず加速度センサーのZ軸を重力方向に置いたときの加速度センサーの値を(x1,y1,z1)=(0,0,1)とします。 加速度センサーのx軸、y軸、z軸をそれぞれ回転させたあとの加速度センサーの値を(x2,y2,z2)とします (このとき加速度センサーは静止しているので、センサーの値は重力の分力になります)。 (x2,y2,z2)が既知のとき(x1,y1,z1)に戻すためのそれぞれの回転角はどのように求めれば良いのか教えてください。 (x2,y2,z2)→(x1,y1,z1)へ移動するときの回転角を φ(z軸の回転角)、ψ(x軸の回転角)、θ(y軸の回転角) とします。 回転行列 (x1) = (cosφ -sinφ 0) (cosθ 0 sinθ) (1 0 0 ) (x2) (y1) = (sinφ cosφ 0) (0 1 0 ) (0 cosψ -sinψ) (y2) (z1) = (0 0 1) (-sinθ 0 cosθ) (0 sinψ cosψ ) (z2) より,3行3列の行列を計算すると 0=cosφcosθx2 + (-sinφcosψ+cosφsinθsinψ)y2+(sinφsinψ+cosφsinθcosψ)z2 0=sinφcosθx2 + (cosφcosψ+sinφsinθsinψ)y2+(-cosφsinψ+sinφsinθcosψ)z2 1=-sinθx2 + cosθsinψy2 + cosθcosψz2 となると思うのですが、この式からφ、ψ、θが導きだせません。 どうすれば求めることができるか教えていただけますか。

  • 回転移動した平面の方程式

    右手系座標での平面 z = 0 を 方位角 φ ( y 軸正方向から見て時計回りを正とする)、 仰角 θ ( x 軸正方向から見て反時計回りを正とする)で 回転させたときの方程式はどのようになりますか。 2つの方法で方程式が一致しないので、 混乱しています。 方位角 φ の座標変換 x' = x cos φ - z sin φ z' = x sin φ + z cos φ 仰角 θ の座標変換 y' = y cos θ + z sin θ z' = - y sin θ + z cos θ 方位角 φ, 仰角 θ の座標変換 (←この辺りから間違っている?) x' = x cos φ - z sin φ y' = x sin φ sin θ + y cos θ + z cos φ sin θ z' = x sin φ cos θ - y sin θ + z cos φ cos θ 方法1 回転後の平面は z' = 0 であるから、平面の方程式は x sin φ cos θ - y sin θ + z cos φ cos θ = 0 方法2 平面 z = 0 の単位法線ベクトル n は (0, 0, 1) である。 座標変換の式にこれを代入すると、回転後の n は ( - sin φ, cos φ sin θ, cos φ cos θ ) であるから、n に垂直で原点を通る平面の方程式は - x sin φ + y cos φ sin θ + z cos φ cos θ = 0 回転放物面 z = ( x^2 + y^2 ) / ( 4 f )についても 方程式を得たいので、よろしくお願い致します。

  • なぜ回転行列が以下のようになるのでしょうか。

    3次元の座標系があります。軸はX,Y,Zです。 Cθ=cosθ Sθ=sinθ でなぜ画像のようになるのかが分かりません。 画像の左上がX軸に関してθだけ回転させた回転行列。 同様に、右はY軸に関して、左下はZ軸に関してθだけ回転させた回転行列です。 cosθ,sinθのつく場所はだいたい分かってきたのですが、符号がどうしてそうなるのかが分かりません。 各軸を原点から見て時計回りを正とするそうです。 よろしくお願いします。

  • atan2関数 ベクトル計算・・・

    atan2関数を使用した、ベクトルとベクトルのなす角度を 返す関数 というのを作りたいのですが、いいプログラム例があればご紹介ください。 また、 ベクトルの視点を中心として、 angle(rad) 回転させる 関数について。  回転公式 (x, y) を angle(rad) 回転 → (x', y')  x' = cos(angle)*x + sin(angle)*y  y' = -sin(angle)*x + cos(angle)*y どちらかひとつでも、お分かりになる方がいらしたらよろしく御願いします。

  • 透視投影図形の回転

    C言語で透視投影の図形(3次元)を作成しました。 プログラムは下のような感じになりました。 static struct {int f; double x,y,z;}a[] ...(略) for(j=0; a[j].f!=-999; j++){//-999が来るまで描画  h=-a[j].x*sin(ay)/vp+a[j].z*cos(ay)/vp+n/vp+1;  px=(a[j].x*cos(ay)+a[j].z*sin(ay)+1)/h;  py=(a[j].y+m)/h;   if(a[j].f==-1) //-1が先頭にあるなら    pDC->MoveTo(px+200,-py+200);//描画の始点   else //そうでないなら    pDC->LineTo(px+200,-py+200);//線の終点 } これに、わかっているx軸まわり・y軸まわりの回転変換マトリックスを掛け合わせた、統合変換マトリックスの式 x=x*cosθ-z*sinθ y=x*sin^2θ+y*cosθ+z*sinθcosθ z=x*sinθcosθ-y*sinθ+z*cos^2θ を使用して図形を回転させたいのですが、プログラム中にはpDC->MoveTo(px+200,-py+200);のようにxとyしか出力がなく、z=をどう出力しようかと悩んでいます。また、回転を表示させるのに、 描画→回転させたx,y座標の算出→一度画面を白く塗りつぶす→描画 ということをfor文でやっていこうと思うのですが、画面がとてもちらついてしまいます。ちらつかない方法があれば教えてください。

  • ベクトルの回転について

    はじめまして。 以下のような問題について大学1年生の弟から質問されたのですが、 答えに自信がありません。どうか皆様のお力をお貸しください。 三次元空間上にベクトルA(ax,ay,az)、B(bx,by,bz)がある。 このAがBと平行になるような計算をしたい。 自分なりの考えは以下の通りです。 1.z座標を無視して、xy平面上のベクトルとして考え、成す角θzを求める θz=ArcCos{<A,B>/|A||B|} |A|=√ax^2+ay^2 |B|=√bx^2+by^2 <A,B>=ax×bx+ay×by 2.x座標を無視して、xy平面上のベクトルとして考え、成す角θxを求める θx=ArcCos{<A,B>/|A||B|} |A|=√ay^2+az^2 |B|=√by^2+bz^2 <A,B>=ay×by+az×bz 3.y座標を無視して、xy平面上のベクトルとして考え、成す角θyを求める θy=ArcCos{<A,B>/|A||B|} |A|=√ax^2+az^2 |B|=√bx^2+bz^2 <A,B>=ax×bx+az×bz 4.z軸回転させる。このとき、z軸回転させた座標をzAx、zAyとする。 zAx=ax Cosθz-ay Sinθz zAy=ax Sinθz + ay Cosθz 5.次にx軸回転させる。このとき、x軸回転させた座標をxAy、xAzとする。 xAy=zAy Cosθx-az Sinθx  xAz=zAy Sinθx + az Sinθx 6.次にy軸回転させる。このとき、y軸回転させた座標をyAx、yAzとする。  yAz=xAz Cosθy-zAx Sinθy yAx=xAz Sinθy + zAx Cosθy 7.求まったyAx、zAy、yAzを成分とする、ベクトルはBと平行である。(終了) うろ覚えですが、軸回転は順番によって全く違った回転をしてしまうというのを昔勉強したような気がするのですが、今回の場合は特にそういった問題は関係ないのでしょうか? また、それぞれの平面ごとになす角を求め、3つのなす角を使った回転を行ないましたが、 θ=ArcCos{<A,B>/|A||B|} |A|=√ax^2+ay^2+az^2 |B|=√bx^2+by^2+bz^2 <A,B>=ax×bx+ay×by+az×bz といった風に、一気に求めたθを用いて回転させる方法はありませんでしょうか? (AとBの外積で出てくる値が回転軸になるような・・・・?) 宜しくお願いします。

  • 座標軸の回転と楕円の方程式

    原点Oを中心に回転した座標系で、元の座標系で楕円の方程式を表す方程式は、どう変わるかがわからないので質問します。 問題は、Oxy軸をOのまわりに120°回転して、Ox'y'軸が得られたとする。このときOxy系で楕円x^2/9+y^2/4=1を表す方程式は、Ox'y'系でどのような方程式になるか?です。 以下では、{}で行列を表し、(,,・・・)で一行分の要素を列挙し,左の()から1行、2行・・・とします。例えば、{(cos120°,-sin120°),(sin120°,cos120°)}の2行1列目の要素は、sin120°です。 自分は、{(x),(y)}={(cos120°,-sin120°),(sin120°,cos120°)}*{(x'),(y')}より、x=-1/2x'-√3/2y'とy=√3/2x'-1/2y'を得て、x^2/9+y^2/4=1に代入しました。そうして31x'^2-10√3x'y'+21y'^2=144を答えとしたのですが、 本の解答は、31x'^2-10√3x'y'-21y'^2=144でした。どなたか正しい答えを教えていただけませんかお願いします。

  • オイラー角 回転行列

    オイラー角 回転行列 オイラー角と回転行列の関係が良く理解出来ないので 質問させて下さい。 工学や物理学で使われるオイラー角の回転順序は Z-X-Zが一般的だと認識しています。 ここで、3次元空間でのX軸、Y軸、Z軸周りの回転を 表す回転行列は、   1  0  0 Rx= 0 cosθ -sinθ 0 sinθ cosθ   cosθ 0 sinθ Ry= 0  1 0 -sinθ 0 cosθ    cosθ -sinθ 0 Rz= sinθ cosθ 0 0   0  1 です。 それぞれのθが、その軸での回転だと認識しています。 ここで、回転の方向はRxはY軸をZ軸に向ける方向、 RyはZ軸をX軸に向ける方向、RzはX軸をY軸に向ける方向。 Z-X-Zとは、 Rz・Rx・Rzの積という認識で良いでしょうか? 例えば、 Rx:Y軸をZ軸に向ける方向にπ/2 Ry:Z軸をX軸に向ける方向にπ/3 Rz:X軸をY軸に向ける方向にπ/4 回転させたとします。 Rz・Rx・Rzの積でなぜ、Ryの回転 が表現できるのですか? また、オイラー角はα,β,γと表記される事もありますが、 これは、X軸回転をα、Y軸回転をβ、Z軸回転をγで表して いるという事なのでしょうか? 分からない点だらけで申し訳御座いませんが、ご回答何卒よろしくお願い致します。

  • 回転行列によって面積が変更されないことの証明

    現在、表題のとおりの問題で困っています。 平面上に三角形を構成する3点があるとき、下記の一次変換によってその3点を移動することを考えます。 回転行列 | X | = | cosβ -sinβ || x | | Y |   | sinβ cosβ  || y | このとき、移動先の3点によって構成される三角形の面積が元の三角形の面積と変わらないことを証明したいのですが、どうしたら良いのでしょうか。 ご教授ください。

専門家に質問してみよう