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

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

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

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

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

Q&A

解決済

3回答

4189閲覧

射影変換がうまくできない

_pumpkin

総合スコア30

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

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

0グッド

0クリップ

投稿2016/04/19 13:50

編集2016/04/23 06:43

###前提・実現したいこと
c++で射影変換をするプログラムを作っております。(Eigen導入)
できれば、opencv等のライブラリは導入しない方向です。
###発生している問題・エラーメッセージ
変換後の画像が変換したい四角形におさまらず、歪んだ画像になってしまいます。
元画像...256 * 256
青い四角が変換したい位置で、Aとかかれた図形が変換後の図形です。
###該当のソースコード
//指摘された通りに内容を変更しました
void getSystem(POINTd* in,POINTd* out,double *ht) {//8個のパラメータを求める
Matrix<double, 8 , 8> dATA;
dATA<< in[0].x, in[0].y, 1, 0, 0, 0, -out[0].x * in[0].x, -out[0].x * in[0].y,
in[1].x, in[1].y, 1, 0, 0, 0, -out[1].x * in[1].x, -out[1].x * in[1].y,
in[2].x, in[2].y, 1, 0, 0, 0, -out[2].x * in[2].x, -out[2].x * in[2].y,
in[3].x, in[3].y, 1, 0, 0, 0, -out[3].x * in[3].x, -out[3].x * in[3].y,
0, 0, 0, in[0].x, in[0].y, 1, -out[0].y * in[0].x, -out[0].y * in[0].y,
0, 0, 0, in[1].x, in[1].y, 1, -out[1].y * in[1].x, -out[1].y * in[1].y,
0, 0, 0, in[2].x, in[2].y, 1, -out[2].y * in[2].x, -out[2].y * in[2].y,
0, 0, 0, in[3].x, in[3].y, 1, -out[3].y * in[3].x, -out[3].y * in[3].y;
dATA = dATA.inverse();
for (int i = 0; i < 8; i++) {
ht[i] = 0;
for (int j = 0; j < 4; j++) {
ht[i] +=
dATA(i, j) * out[j].x;
}
for (int j = 0; j < 4; j++) {
ht[i] +=
dATA(i, j + 4) * out[j].y;
}
}
}

void draw(){//求めたパラメータから実際にイメージ(DIB)に描画する
/* 変数の定義など */
double ht[8] = { 0 };
getSystem(pointin, pointout,ht);
for(int x = 0;x < image_src.Width;x++){
for(int y = 0;y < image_src.Height;y++){
int x1 = (double)x * ht[0] + (double)y * ht[1] + ht[2] /
((double)x * ht[6] + (double)y * ht[7] + 1.0);
int y1 = (double)x * ht[3] + (double)y * ht[4] + ht[5] /
((double)x * ht[6] + (double)y * ht[7] + 1.0);
if (x1 > Width)x1 = 0;
if (y1 > Height)y1 = 0;
if (x1 < 0)x1 = 0;
if (y1 < 0)y1 = 0;
lpPixel_target[x1 + y1 * Width] = image_src.GetPixel(x,y);
}
}
}
###試したこと
参考サイト:

http://yaju3d.hatenablog.jp/entry/2013/08/04/152524
http://mf-atelier.sakura.ne.jp/mf-atelier/modules/tips/program/algorithm/a6.html

ネットで調べる限り調べましたが、結果は変わりませんでした。

###補足情報(言語/FW/ツール等のバージョンなど)
visualstudio 2015 c++
Eigen導入済み

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

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

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

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

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

yohhoy

2016/04/23 02:57

「歪んだ画像」はどのように確認しましたか?また、画像幅image_src.Widthは何pixelですか?(DIBデータは4の倍数以外の扱いに癖があります)
_pumpkin

2016/04/23 06:44

画像の青い四角が変換したい四角形で、'A'とかかれたのが実際のコードで作った変換後の画像です。
guest

回答3

0

getSystem関数の戻り値に、ローカル変数として関数内で定義した配列のポインタを返していますが、C/C++ではその方法は御法度です。getSystemから抜けたときにdATA2は破棄されるため、htで受け取ったポインタの指す場所には別の値で上書きされてしまった可能性があります。

呼び出し側で配列変数を定義し、そのポインタをgetSystem関数に渡して、そこに計算結果を格納するようにしてください。

こんな感じ

C++

1double* getSystem(POINTd* in,POINTd* out) 23void getSystem(POINTd* in,POINTd* out, double dATA2[]) 4// double dATA2[8] = { 0.0 }; と return dATA2; は不要なので削除

C++

1// draw関数の中 2double ht[8] = { 0.0 }; // 呼び出し側で配列変数を定義 3getSystem(pointin, pointout, ht);

投稿2016/04/19 14:55

catsforepaw

総合スコア5938

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

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

_pumpkin

2016/04/20 05:47

その通りにやってみたのですが、結果は変わりませんでした。 (visual studioだとローカルなポインタを返しても大丈夫?)
catsforepaw

2016/04/20 09:50

Visual Studioだとローカルなポインタを返して良いということはありません。 結果が変わらないとなると、別のところに原因があるのかもしれませんね。射影変換についてはやったことがないので具体的にアドバイスすることはできないのですが、他の人が試せる形のコードを提示して、どのようにゆがんでいるのかを説明していただければ、その方面に詳しい人からのアドバイスをもらえるかもしれません。
guest

0

catsforepawさんが書かれた方法が安全で私もお勧めだと思いますが、どうしてもgetSystem()をポインタを返す関数にしたい場合、関数内でnewした変数を返すことで実現できます。

C++

1double dATA2[8] = { 0.0 }; 23double* dATA2 = new double[8];

ただ、これだと呼び出し側でちゃんとdelete[]してやらないといけませんし、戻り値のポインタのNULLチェックもしなければいけないので、getSystem()を使う側も注意が必要になります。

上記の例はあくまでも「そういう方法もある」程度に解釈していただければと思います。

投稿2016/04/20 03:38

編集2016/04/20 03:39
KoichiSugiyama

総合スコア3041

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

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

0

ベストアンサー

x1, y1計算時の分子がおかしいのでは?

部分式(double)x * ht[0] + (double)y * ht[1] + ht[2]を括弧でくくる必要があるかと思います。

投稿2016/04/23 07:33

yohhoy

総合スコア6191

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

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

_pumpkin

2016/04/23 08:03

できました! 何時間も悩んでいたのに演算子の優先順位とは... 本当にありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問