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

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

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

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

C++

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

Q&A

解決済

3回答

8303閲覧

opencvでの画像の回転

yamata

総合スコア36

OpenCV

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

C++

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

0グッド

0クリップ

投稿2016/07/12 04:09

編集2016/07/12 12:43

opencvを用いて読み込んだ画像の回転を行っています。
以下のプログラムで画像の回転を行い実行できたのですが、
画像が回転し、元の画像の場所が黒く表示されるのが気に入りません。
表示するウィンドウごと回転することは出来ないのでしょうか?

この画像の黒い部分をなくすように
ウインドウを表示するということです。
回転した画像と同じだけ回転させたウインドウを表示するようなことです。
回転した画像にマッチングを行いたいと考えているのですが、、、

使用環境は、VC++2010Express、opencv2.4.9です。

よろしくお願いします。

#define SCALE 0.8 // 画像の拡大率 int main( int argc, char **argv ) { char windowNameSource[] = "Source"; // 元画像を表示するウィンドウの名前 char windowNameDestination[] = "Destination"; // 変換後の画像を表示するウィンドウの名前 // 画像を読み込む IplImage *sourceImage = cvLoadImage( "image/lena.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR ); if ( sourceImage == NULL ){ // 画像が見つからなかった場合 printf( "画像が見つかりません\n" ); return -1; } // 画像を生成する IplImage *destinationImage = cvCreateImage( cvGetSize( sourceImage ), IPL_DEPTH_8U, 3 ); // 変換後の画像用IplImage CvPoint2D32f center = cvPoint2D32f( sourceImage->width / 2.0, sourceImage->height / 2.0); //回転中心 // 行列を生成する CvMat *rotationMatrix = cvCreateMat( 2, 3, CV_32FC1 ); // 回転行列 // 変換行列を求める cv2DRotationMatrix( center, ANGLE, SCALE, rotationMatrix); // 画像の拡大、縮小、回転を行う cvWarpAffine( sourceImage, destinationImage, rotationMatrix, CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS, cvScalarAll( 0 ) ); // ウィンドウを生成する cvNamedWindow( windowNameSource, CV_WINDOW_AUTOSIZE ); cvNamedWindow( windowNameDestination, CV_WINDOW_AUTOSIZE ); // 画像を表示する cvShowImage( windowNameSource, sourceImage ); cvShowImage( windowNameDestination, destinationImage ); // キー入力を待つ cvWaitKey( 0 ); // 画像を保存する cvSaveImage( "image/destination.bmp", destinationImage ); // メモリを解放する cvReleaseImage( &sourceImage ); cvReleaseImage( &destinationImage ); // ウィンドウを破棄する cvDestroyWindow( windowNameSource ); cvDestroyWindow( windowNameDestination ); return 0; }

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

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

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

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

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

guest

回答3

0

ウィンドウを回転させることはWindowsにその機能が搭載されていないのでできませんが、ウィンドウの枠や背景を表示させずに斜めの画像だけを表示させることならできます。

その方法は三つあります。

  1. 画像に合わせたリージョンをウィンドウに設定し、画像部分だけを表示
  2. レイヤードウィンドウカラーキーによる画像部分以外の透明化
  3. レイヤードウィンドウアルファチャンネルによる画像部分以外の透明化

1はSetWindowRgn関数、2と3はレイヤードウィンドウに設定した上でSetLayeredWindowAttributes関数とUpdateLayeredWindow関数で、比較的簡単に実現可能です。

ただし、OpenCVのウィンドウ表示機能では細かい制御ができないので、自前でウィンドウを作成/表示させないと無理かもしれません。


追記
カラーキーを指定して、その色の部分を透過させるウィンドウの実装例です。画像ファイルのパスや背景のサイズは適当に調整してください。

C++

1#include "opencv2\opencv.hpp" 2#include <windows.h> 3#include <atlbase.h> 4#include <atlwin.h> 5 6// cv::waitKeyの自前実装版 7static int sKey = 0; 8int myWaitKey(int iWaitTime) 9{ 10 ULONGLONG timeup = ::GetTickCount64() + iWaitTime; 11 do 12 { 13 MSG msg; 14 while(::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) 15 { 16 if(msg.message == WM_QUIT) 17 return -1; 18 ::TranslateMessage(&msg); 19 ::DispatchMessage(&msg); 20 } 21 } while(sKey == 0 && (iWaitTime == 0 || ::GetTickCount64() < timeup)); 22 int key = sKey; 23 sKey = 0; 24 return key; 25} 26 27// カラーキーを使った透過ウィンドウの実装例 28class ColorKeyWindow : public ATL::CWindowImpl<ColorKeyWindow> 29{ 30 cv::Mat mImage; 31 32public: 33 DECLARE_WND_CLASS(L"ColorKeyWindow-Class"); 34 35 // コンストラクタでウィンドウを作成し、カラーキーを設定 36 ColorKeyWindow(const wchar_t * iName, COLORREF iColorKey = RGB(0,0,255)) 37 { 38 RECT rc = {0, 0, 0, 0}; 39 HWND hwnd = this->Create(nullptr, rc, iName, WS_POPUP, WS_EX_LAYERED); 40 ::SetLayeredWindowAttributes(hwnd, iColorKey, 0, LWA_COLORKEY); 41 } 42 43 // デストラクタでウィンドウ破棄 44 ~ColorKeyWindow() 45 { 46 this->DestroyWindow(); 47 } 48 49 // 画像表示 50 void ShowImage(const cv::Mat & iMat) 51 { 52 mImage = iMat.clone(); 53 this->SetWindowPos(nullptr, 0, 0, mImage.cols, mImage.rows, SWP_NOMOVE|SWP_NOZORDER|SWP_SHOWWINDOW); 54 // 実際にはWM_PAINTで表示 55 this->Invalidate(FALSE); 56 } 57 58private: 59 BEGIN_MSG_MAP(HelloWindow) 60 MESSAGE_HANDLER(WM_PAINT, OnPaint) 61 MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest) 62 MESSAGE_HANDLER(WM_CHAR, OnChar) 63 END_MSG_MAP() 64 65 LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 66 { 67 PAINTSTRUCT ps; 68 HDC hdc = BeginPaint(&ps); 69 if(!mImage.empty()) 70 { 71 BITMAPINFO bmi = {0}; 72 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 73 bmi.bmiHeader.biWidth = mImage.cols; 74 bmi.bmiHeader.biHeight = -mImage.rows; 75 bmi.bmiHeader.biPlanes = 1; 76 bmi.bmiHeader.biBitCount = mImage.channels() * 8; 77 bmi.bmiHeader.biClrImportant = BI_RGB; 78 ::SetDIBitsToDevice(hdc, 0, 0, mImage.cols, mImage.rows, 0, 0, 0, mImage.rows, mImage.ptr(0), &bmi, DIB_RGB_COLORS); 79 } 80 EndPaint(&ps); 81 return 0; 82 } 83 84 LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 85 { 86 // ウィンドウをマウスで移動できるようにする 87 return HTCAPTION; 88 } 89 90 LRESULT OnChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 91 { 92 sKey = (int)wParam; 93 return 0; 94 } 95}; 96 97// サンプルプログラム 98int main(int argc, char* argv[]) 99{ 100 cv::Mat image = cv::imread("lena.jpg"); 101 cv::Mat bgimage(cv::Size(800, 800), CV_8UC3); 102 103 ColorKeyWindow window(L"MyWindow"); 104 105 int angle = 0; 106 while(1) 107 { 108 bgimage = cv::Scalar(255, 0, 0); // ブルーバックでクリア 109 110 cv::Point2d center(image.cols / 2, image.rows / 2); 111 cv::Mat mat = cv::getRotationMatrix2D(center, angle, 1.0); 112 mat.at<double>(0, 2) += (bgimage.cols - image.cols) / 2; 113 mat.at<double>(1, 2) += (bgimage.rows - image.rows) / 2; 114 cv::warpAffine(image, bgimage, mat, bgimage.size(), cv::INTER_LINEAR, cv::BORDER_TRANSPARENT); 115 angle = (angle + 360 - 1) % 360; 116 117 window.ShowImage(bgimage); 118 119 int key = myWaitKey(1); 120 if(key == '\x1b') 121 break; 122 } 123 return 0; 124}

投稿2016/07/12 06:56

編集2016/07/12 14:27
catsforepaw

総合スコア5938

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

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

yamata

2016/07/12 12:39

ありがとうございます。 回転した画像でテンプレートマッチングを行いたいと考えていたのですが、 難しそうですね。
catsforepaw

2016/07/12 14:24

軽く試してみましたが、やはりOpenCVのウィンドウではうまくできなかったので、自前のウィンドウで作ってみました。回答にサンプルコードを追記します。
yamata

2016/07/12 14:37

ありがとうございます!試してみてわからないことがあれば、 また質問するかもしれませんが、よろしくお願いします。
guest

0

投稿2016/07/12 05:38

episteme

総合スコア16614

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

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

yamata

2016/07/12 12:32

ありがとうございます。 具体的な方法を教えていただけたらと思います。
episteme

2016/07/12 13:37

スクローラ付きのimageペインをくるくる回すのはWPFで一行のコードも書かずに実現できます。
yamata

2016/07/12 14:32

試してみたいと思います。
yamata

2016/07/12 14:39

ありがとうございます
guest

0

ベストアンサー

こんにちは。

普通のウィンドウは辺が水平・垂直のものだけですが、斜めの辺のウィンドウを表示したいということでしょうか?

もし、そうであればOpenCVはサポートしていない筈です。
Windows APIで任意形状のウィンドウ表示はできます。すぐには出てこないのですが、昔実装したことがあります。
.NETを使えば簡単にできるようなので、UI部をC++/CLIで実装することも考えられると思います。

でも、どちらがたいへんか微妙です。任意形状のウィンドウ表示も多少面倒ですが、C++/CLIを新たに使いはじめることと大差ないような気がします。

投稿2016/07/12 04:26

Chironian

総合スコア23272

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

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

yamata

2016/07/12 12:31

ありがとうございます。 回転した画像と同じだけ回転したウインドウを表示したいということです。
Chironian

2016/07/12 13:04

Windowsにウィンドウを回転させる機能はありません。 従って、回転したかのように見えるウィンドウを表示するしかないです。 そのためには、黒い部分をウィンドウ領域でないように指定することになります。 catsforepawさんが書かれてますが、SetWindowRgn()を使えば可能です。(他の方法は使ったことないので私は良く分かりません。) 「ウィンドウの形状を変更してみる」(http://chokuto.ifdef.jp/urawaza/windowrgn.html)に解説がありました。このサイトでは楕円や星形のウィンドウを表示してますが、それらの代わりに回転した矩形のウィンドウを表示することになります。 また、「.NETを使えば簡単にできる」のリンク先に、epistemeさんが示したサンプルのようなウィンドウを表示する方法が解説されてます。
Chironian

2016/07/12 13:08

> 回転した画像にマッチングを行いたいと考えているのですが、、、 この意味が良く分かりません。 画像マッチングは表示とは無関係と思います。回転していてもしてなくても、更には表示してなくてもテンプレート・マッチングのような処理は、(当たり前ですが)可能です。 具体例を書いて頂けると理解しやすいかも知れません。
yamata

2016/07/12 14:36

言葉足らずですいません。 具体的に書きますと、入力画像を用意し、テンプレートの角度を変えながら テンプレートマッチングを行いたいと考えています。 現状では、テンプレートの角度を変えると、ウィンドウ内に黒い領域が現れ 正確なマッチングを行えません。 この問題を解決したいと考えています。
Chironian

2016/07/12 14:52

なるほど。 ということは、ウィンドウ表示の話は無関係ですね。 そのような時は、テンプレートの元画像を少し広い範囲で回転させ、周囲の黒い部分を避けて「まっすぐな」矩形を取り出し、テンプレート画像とするのが良いと思います。 テンプレート・マッチング処理側で斜めのテンプレート画像に対応することも考えられますが、大きく速度が落ちそうですし、OpenCVのテンプレート・マッチングは斜めのテンプレート画像に対応してなかったと思います。
episteme

2016/07/12 23:17

[ちなみに] WPFではform内に貼りつけたコントロールを"傾ける"ことができて、このときコントロールに貼りつけたイメージを回転させる必要は"ありません"。
yamata

2016/07/13 02:42

ありがとうございます。 あまりよくわからないので、簡単なプログラムを教えていただくことは できないでしょうか?
episteme

2016/07/13 02:49

コードを示すことはできますが、C#だしXAMLだし、経験ないと簡単じゃないですよ?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問