ウィンドウを回転させることはWindowsにその機能が搭載されていないのでできませんが、ウィンドウの枠や背景を表示させずに斜めの画像だけを表示させることならできます。
その方法は三つあります。
- 画像に合わせたリージョンをウィンドウに設定し、画像部分だけを表示
- レイヤードウィンドウのカラーキーによる画像部分以外の透明化
- レイヤードウィンドウのアルファチャンネルによる画像部分以外の透明化
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 12:39
2016/07/12 14:24
2016/07/12 14:37