質問するログイン新規登録

回答編集履歴

2

サンプルコード追記

2016/07/12 14:27

投稿

catsforepaw
catsforepaw

スコア5944

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

1

書き忘れ

2016/07/12 14:27

投稿

catsforepaw
catsforepaw

スコア5944

answer CHANGED
@@ -6,6 +6,6 @@
6
6
  2. **レイヤードウィンドウ**の**カラーキー**による画像部分以外の透明化
7
7
  3. **レイヤードウィンドウ**の**アルファチャンネル**による画像部分以外の透明化
8
8
 
9
- 1は`SetWindowRgn`関数、2と3はレイヤードウィンドウに設定した上で`SetLayeredWindowAttributes`関数で、比較的簡単に実現可能です。
9
+ 1は`SetWindowRgn`関数、2と3はレイヤードウィンドウに設定した上で`SetLayeredWindowAttributes`関数と`UpdateLayeredWindow`関数で、比較的簡単に実現可能です。
10
10
 
11
11
  ただし、OpenCVのウィンドウ表示機能では細かい制御ができないので、自前でウィンドウを作成/表示させないと無理かもしれません。