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

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

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

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

OpenCV

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

C++

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

Q&A

3回答

4549閲覧

OpenCVで透明なウィンドウを作りたい

moss3055

総合スコア12

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

OpenCV

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

C++

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

0グッド

0クリップ

投稿2019/07/17 00:15

前提・実現したいこと

こんにちは.
プログラミング初心者です.
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ページで確認できます。

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

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

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

guest

回答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
fana

総合スコア11656

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

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

fana

2019/07/19 02:57

※ビットマップデータのパディングに関する問題を回避するために,この例では横幅が4の倍数な画像を用いています.
moss3055

2019/07/19 21:11

詳しくお教えいただき,誠にありがとうございます. 私の方でもこちらのプログラムが実行できるかどうか確認してみましたが,所々にエラーが出てしまい,実行できませんでした... (例えば,MessageBox(NULL, "Img Read Err", "ERR", MB_OK); return 0; のところで,「型"const char*"の引数は型"LPCWSTR"のパラメーターと互換性がありません」と出たり, MAKEINTRESOURCEの識別子"IDC_LAYERWNDTEST"が定義されてない等...)
fana

2019/07/20 00:56

「やったこと:」の部分を参考にしてください. 「//★」で囲まれている箇所の要素をご自身のプログラムに取り込むような形で. コードだけを丸ごと持っていくとそのような問題が発生するはずです. ・MessageBoxの側は,プロジェクト設定が「UNICODE文字セットを使用する」になっているんじゃないかと思います. ・IDC_LAYERWNDTESTの側は自動生成されたリソースの識別子なので,作ったプロジェクトの名前によって識別子の名称が変わるはずです.
fana

2019/07/20 00:57

あと,VisualStudioのバージョンでも自動生成されるコードの具合が違うかもです.
moss3055

2019/07/24 22:04

ご指摘くだたっさ点に注意して,もう一度プログラムを作成したところ, エラーはなくなったものの,リビルドが失敗に終わります...
fana

2019/07/25 02:14

エラーは無いけどビルドは失敗 という現象はよくわからないです. (可能ならば,それを主題とした質問をされてみてはどうでしょう?)
guest

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

fana

総合スコア11656

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

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

moss3055

2019/07/18 22:15

ご回答ありがとうございます. 「画像を表示するためのWS_EX_LAYEREDなウィンドウを自前で用意する」とはどういうことでしょうか?
fana

2019/07/19 01:22 編集

(OpenCVを使わないプログラムでウィンドウを作る場合と同様に)例えばWin32APIならCreateWindowEx()等のAPIを用いてウィンドウを生成するということです. で,そのウィンドウに cv::Mat 型で保持している画像を表示すれば良いという話です. 8UC3でBGRなフォーマットなら画素データの並びは(上下の方向とパディング以外は)WindowsBitmapと同様なので,Matに見合うBITMAPINFOHEADERを用意してやればSetDIBitsToDevice()あたりで描画できるでしょう.
fana

2019/07/19 02:45

回答を別に分けて,ちょいとやってみたことを書きました.
guest

0

OpenCVで透明なウィンドウを作成することは出来ません。

この辺から有益な情報は得られませんか?

投稿2019/07/17 01:21

Ryupe

総合スコア426

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

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

moss3055

2019/07/17 23:25

ご回答ありがとうございます. OpenCVでは作成できないのですね... ちなみにOpenGLだったら作成できますでしょうか?
Ryupe

2019/07/18 00:51

OpenGLは触ったことが無いので分かりません。
moss3055

2019/07/18 01:15

わかりました. OpenCVで作成したウィンドウをSetLayeredWindowAttributesなどで透明にすることは可能ですかね? ご教示くださったところから色々探してみたのですが,まだよく理解できていなくて...
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問