前提・実現したいこと
こんにちは.
プログラミング初心者です.
OpenCV使って透明なウィンドウを作り,そこに図形を描けるようにしたいです.
何かいい方法はありますでしょうか.
該当のソースコード
C++
1Mat img(Size(1920, 1080), CV_8UC3, Scalar(255, 255, 255));
試したこと
現在,上記のコードを使って真っ白なウィンドウを作ることはできました.
これを透明色にしたく,「CV_8UC3, Scalar(255, 255, 255)」のところを「CV_8UC4, Scalar(255, 255, 255, 0)」で試してみましたが,真っ白なウィンドウのままでした.
補足情報(FW/ツールのバージョンなど)
使用言語はc++です.また,Visual Studio 2017を使用しプログラムを作成しています.
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答3件
0
とりあえず自前ウィンドウでやってみました.(VS2017 + OpenCV4.0.0)
白( (R,G,B)=(255,255,255) )箇所を透過しています.
やったこと:
- 「Windowsデスクトップアプリケーション」を新規に作り
- (OpenCV使うのに面倒なので)プロジェクト設定で「マルチ バイト文字セットを使用する」に.
- 自動生成されたコードに対して,下記コードで「//★」で囲まれている箇所を追記.
(加えて,不要な箇所は適当にコメントアウトしています)
#include "stdafx.h" #include "LayerWndTest.h" //※プロジェクト名を"LayerWndTest"として作った //★include #include "opencv2/core.hpp" #include "opencv2/highgui.hpp" #include <string> //★ //#define MAX_LOADSTRING 100 // グローバル変数: HINSTANCE hInst; // 現在のインターフェイス //WCHAR szTitle[MAX_LOADSTRING]; // タイトル バーのテキスト //WCHAR szWindowClass[MAX_LOADSTRING]; // メイン ウィンドウ クラス名 //★データはとりあえずグローバルで const std::string WndClassName = "MyWndClass"; // メイン ウィンドウ クラス名 cv::Mat TheImg; //画像 BITMAPINFO TheBMPI; //画像表示に使う //★ // このコード モジュールに含まれる関数の宣言を転送します: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); //★画像読込とBITMAPINFOHEADERの中身設定 TheImg = cv::imread("Cat.png"); if(TheImg.empty()) { MessageBox(NULL, "Img Read Err", "ERR", MB_OK); return 0; } BITMAPINFOHEADER *pBMIF = &(TheBMPI.bmiHeader); memset(pBMIF, 0, sizeof(BITMAPINFOHEADER)); pBMIF->biSize = sizeof(BITMAPINFOHEADER); pBMIF->biPlanes = 1; pBMIF->biCompression = BI_RGB; pBMIF->biWidth = TheImg.cols; pBMIF->biHeight = -abs(TheImg.rows); //※そのままだと上下反転するので対策 pBMIF->biBitCount = WORD(TheImg.channels() * 8); //★ // グローバル文字列を初期化しています。 //LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); //LoadStringW(hInstance, IDC_LAYERWNDTEST, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // アプリケーションの初期化を実行します: if(!InitInstance (hInstance, nCmdShow)) { return FALSE; } HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_LAYERWNDTEST)); MSG msg; // メイン メッセージ ループ: while(GetMessage(&msg, nullptr, 0, 0)) { if(!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int)msg.wParam; } // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX/*W*/ wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LAYERWNDTEST)); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = MAKEINTRESOURCE/*W*/(IDC_LAYERWNDTEST); wcex.lpszClassName = WndClassName.c_str(); wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx/*W*/(&wcex); } // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // グローバル変数にインスタンス処理を格納します。 // HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, // CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr); //★ HWND hWnd = CreateWindowEx( WS_EX_LAYERED, //拡張ウィンドウスタイルでWS_EX_LAYEREDを指定 WndClassName.c_str(), //ウィンドウクラス名 "TestWnd", //ウィンドウタイトル WS_OVERLAPPEDWINDOW, //スタイル 100, 100, 320, 240, //ウィンドウの位置とサイズ NULL, NULL, hInstance, NULL ); SetLayeredWindowAttributes(hWnd, RGB(255, 255, 255), 0, LWA_COLORKEY); //白を透過するように設定 //★ if(!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_COMMAND: { int wmId = LOWORD(wParam); // 選択されたメニューの解析: switch(wmId) { //case IDM_ABOUT: // DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); // break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); //★画像を描画 ::SetDIBitsToDevice(hdc, 0, 0, TheImg.cols, TheImg.rows, 0, 0, 0, TheImg.rows, TheImg.data, &TheBMPI, DIB_RGB_COLORS ); //★ EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
投稿2019/07/19 02:44
編集2019/07/19 02:47総合スコア12151
0
OpenCVの機能(imshowとか)で表示されるウィンドウは,確か,親子の2段構成になっていたと思います.
親子両者に
SetWindowLongPtr()でWS_EX_LAYEREDを与えてSetLayeredWindowAttributes()を使えば
ひょっとしたら透明にできるのかもしれませんが,試したことはないのでできるかどうかはわかりません.
(子ウィンドウにWS_EX_LAYEREDは使えないと思っていたのですが,Windows8からはいけるみたいです.
https://docs.microsoft.com/ja-jp/windows/win32/winmsg/extended-window-styles)
個人的には,画像を表示するためのWS_EX_LAYEREDなウィンドウを自前で用意した方が楽な気がします.
投稿2019/07/18 02:04
総合スコア12151
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/07/19 02:57
2019/07/19 21:11
2019/07/20 00:56
2019/07/20 00:57
2019/07/24 22:04
2019/07/25 02:14