【Microsoft Edge】お気に入りバーを常に表示する

Microsoft Edgeのお気に入りバーは、デフォルトでは、新しいタブを表示したときのみ表示され、ページ内のリンクをクリックするとお気に入りバーが非表示になってしまいます。

 

 

私はこれまで、Google Chromeを使っていてChromeに慣れているとEdgeでもお気に入りバーは常に表示しておきたい!

ということで、お気に入りバーを常に表示する方法は以下の通りです。

 

  1. (お気に入り)をクリック
  2. (その他のオプション)をクリック
  3. お気に入りバーの表示 にマウスポインタを合わせる
  4. 常に をクリック

 

これで、お気に入りバーは常に表示されるようになります。

 

【Windows11】ウィンドウ外側の影をなくす方法

Windows11ではウィンドウの外側に影が付いて表示されるようになりました。

これは、なんとなく雰囲気はよくなったものの、マニュアルやブログなどの作成時に、ウィンドウのスクリーンショットを撮るときは、邪魔となるケースもあります。

そこで、この影を表示させない方法を紹介します。

ウィンドウ外側の影を消す設定方法

ます、ウィンドウのスタートボタンを右クリックし、表示されたメニューの中からシステムを選択します。

 

表示されたウィンドウの右側にあるシステムの詳細設定をクリックします。

 

次にパフォーマンスの部分にある設定ボタンをクリックします。

 

すると、ウィンドウの下に影を表示するという項目があるので、ここのチェックを外し、適用ボタンをクリックします。

 

これで、設定は完了です。

影があるときと、影が無いときを比較すると、

影あり

影なし

 

個人的にはブログを書くときに影があると邪魔な場合が多いので、影はない方がいいですね。

また、スクリーンショットをウィンドウに合わせて撮影できるアプリなどもありますが、Windows11ではウィンドウの角が丸くなっているので、影があるとスクリーンショット画像の角が少し黒くなってしまうため、やっぱり影は邪魔です。

 

ちなみに、スクリーンショットを撮影するプログラムに Screenpressoというプログラムがあります。
私の中ではマニュアルやブログを書くときには必須のアプリになっていて、おススメです。

無料の画面キャプチャソフト『Screenpresso』

【OpenCV/Python】画像ファイルの読み込み、表示

OpenCVでBmpやJpegなどの画像ファイルを開くには、imread関数を用います。

開いた画像データはimshow関数でウィンドウ付きで画像を表示します。

実際に画像が表示されるのは、waitKey関数が呼ばれたタイミングとなります。

以下に最もシンプルなサンプルを示します。

import cv2

# 画像ファイルの読み込み(カラー画像(3チャンネル)として読み込まれる)
img = cv2.imread("Mandrill.bmp")

# 画像の表示
cv2.imshow("Image", img)

# キー入力待ち(ここで画像が表示される)
cv2.waitKey()

(実行結果)

ここに示したサンプルでは、画像データは必ず8bit x 3ch のデータとなり、表示されたウィンドウはリサイズすることができません。

そのようにしないためには、各関数のオプションを設定します。

詳細は、各関数ごとに説明します。

imread()

bmp, jpeg, png, tiff などの画像ファイルを開きます。

cv2.imread( filename[, flags] ) -> retval
引数 説明
filename 画像のファイル名を指定します。
ただし、日本語は使えません。
flags ファイルを開く際に、カラーデータとして開くか?モノクロデータとして開くか?などを指定します。
指定しない場合、カラーデータ(BGRの3チャンネル)として画像ファイルを開きます。
cv2.IMREAD_UNCHANGED 画像ファイルのフォーマットのまま、画像ファイルを開きます。
cv2.IMREAD_GRAYSCALE   グレースケールに変換して画像ファイルを開きます。
cv2.IMREAD_COLOR          カラーデータ(BGRの3チャンネル)に変換して画像ファイルを開きます。
cv2.IMREAD_ANYDEPTH    画像ファイルのビット深度のまま画像ファイルを開きます。
cv2.IMREAD_ANYCOLOR    画像ファイルの色(チャンネル数)のまま画像ファイルを開きます。(参考)ImreadModes
戻り値 画像の輝度値がnumpyのndarray配列に格納されて返されます。
画像データは画像の左上から格納されています。
グレースケールの場合、[高さ, 幅]の二次元配列になります。
カラーの場合、[高さ, 幅, 色]の三次元配列になります。色の順番は、B,G,R,B,G,R・・・の順で格納されています。

画像ファイル名に日本語ファイルを使いたい場合は、NumPyやPillowを使って日本語ファイルを読み込む事も可能です。詳細は以下のページを参照ください。

日本語の画像ファイル読込・保存

また、imread()関数では、画像ファイルが見つからない場合など、画像ファイル読み込み時にエラーが発生しがちです。その場合の対応は以下のページを参照ください。

imreadで画像ファイルが読み込めないときの対応

 

(参考)

https://docs.opencv.org/4.5.5/d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56

imshow()

画像をウィンドウ付きで表示します。
実際に画面に画像が表示されるのは、cv2.waitKey()関数が呼ばれたタイミングで表示されます。

cv2.imshow( winname, mat ) -> None
引数 説明
winname 表示するウィンドウのタイトルを指定します。
namedWindow()関数で作成したウィンドウと同じwinnameを指定することで、画像を表示するウィンドウを切り替えることもできます。
winnameで指定したウィンドウが無い場合、新しいウィンドウで画像を表示します。
日本語を指定すると文字化けします。
mat 表示する画像データを指定します。
戻り値 なし

 

(参考)

https://docs.opencv.org/4.5.5/d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563

waitKey()

指定時間(mSec)分、キー入力を待ちます。

OpenCVで生成したウィンドウのキー入力イベント待ちとなります。

引数 説明
delay キー入力までの待ち時間をmSec単位で指定します。
値を省略、もしくは 0以下 を指定した場合、無限待ちとなります。
戻り値 入力したキーコードが戻されます。

(参考)

https://docs.opencv.org/4.5.5/d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7

namedWindow()

imshow()関数で表示するためのウィンドウを生成します。

cv2.namedWindow( winname[, flags] ) -> None
引数 説明
winname 表示するウィンドウのタイトルを指定します。
日本語を指定すると文字化けします。
flags ウィンドウのリサイズに関する設定を指定します。
cv2.WINDOW_NORMAL リサイズ可能なウィンドウを生成します。
表示されている画像はウィンドウサイズに合わせてリサイズされます。
cv2.WINDOW_AUTOSIZE 画像のサイズに合わせてウィンドウサイズを調整します。
ウィンドウのリサイズはできません。
他に cv2.WINDOW_FREERATIO, cv2.WINDOW_KEEPRATIO, cv2.WINDOW_GUI_NORMAL, cv2.WINDOW_GUI_EXPANDED の設定がありますが、少なくともWindows環境ではcv2.WINDOW_NORMALと同じ
(参考)WindowFlags
戻り値 なし

生成したウィンドウはdestroyWindow()関数で指定したウィンドウを削除するか、destroyAllWindows()関数で全てのウィンドウを削除するようにします。

(参考)

https://docs.opencv.org/4.5.5/d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b

destroyWindow()

ウィンドウタイトル名を指定してウィンドウを閉じます。

cv2.destroyWindow( winname ) -> None
引数 説明
winname 閉じるウィンドウのタイトルを指定します。
戻り値 なし

(参考)

https://docs.opencv.org/4.5.5/d7/dfc/group__highgui.html#ga851ccdd6961022d1d5b4c4f255dbab34

destroyAllWindows()

表示されているウィンドウ全てを閉じます。

cv2.destroyAllWindows() -> None

(参考)

https://docs.opencv.org/4.5.5/d7/dfc/group__highgui.html#ga6b7fc1c1a8960438156912027b38f481

各種設定を行ったサンプルプログラム

import cv2

# 画像ファイルの読み込み(ファイルフォーマットのまま読み込み)
img1 = cv2.imread("Mandrill.bmp", cv2.IMREAD_UNCHANGED)
img2 = cv2.imread("Text.bmp", cv2.IMREAD_UNCHANGED)

# リサイズ可能なウィンドウの作成
cv2.namedWindow("Image1", cv2.WINDOW_NORMAL)
cv2.namedWindow("Image2", cv2.WINDOW_NORMAL)

# 画像の表示
cv2.imshow("Image1", img1)
cv2.imshow("Image2", img2)

# キー入力待ち(ここで画像が表示される)
cv2.waitKey()

# すべて全てのウィンドウを削除
cv2.destroyAllWindows()

(実行結果)

【C#】各種メモリの最大値(2GB制限)

最近のPCではOSは64ビットで、搭載メモリも8GBぐらいは普通にあるので、C#のプログラムでもメモリを4GBぐらいは普通に確保できそうですが、実際には2BGぐらいで頭打ちになります。

おそらくメモリサイズ(要素数)を計算するときにint型で計算していてint型の最大値(2,147,483,647)を超える事でエラーになる場合が多そうです。

そこで、試しにメモリ確保の処理(配列、Bitmapクラス、Marshal.AllocCoTaskMem)の最大値が、どの程度まで確保できるのか?を確認してみました。

評価環境

  • Windows11 Home 64bit
  • 搭載メモリ 32GB
  • Visual Studio 2019
  • C#(.NET Core 3.1)

 

配列の最大値

よく使うbyte, int, float, doubleの型で試してみたところ、以下の要素数が最大となりました。

var byteArr = new byte[2147483591];
var intArr= new int[2146435071];
var floatArr= new float[2146435071];
var doubleArr= new double[2146435071];

配列の最大値に関しては、メモリのサイズというよりも、要素数のint型の最大値制限になっているようです。

.NET Frameworkの場合、デフォルトでは最大サイズが異なるようです。
詳細は、下記ページを参照ください。

https://docs.microsoft.com/ja-jp/dotnet/framework/configure-apps/file-schema/runtime/gcallowverylargeobjects-element?redirectedfrom=MSDN

Bitmapクラスの最大値

Bitmapクラスの確保には、幅、高さ、PixelFormatの組み合わせが、いろいろできてしまうため、幅の値は固定して、高さを変えながらエラーが出るまで最大の高さを確認しました。

以下が、PixelFormatをFormat8bppIndexed, Format24bppRgb, Format32bppArgbで確認したときの最大のサイズとなります。

var bmp8 = new Bitmap(1024 * 3, 699049, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
var bmp24 = new Bitmap(1024, 699049, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
var bmp32 = new Bitmap(1024, 524287, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

Bitmapクラスに関しては、 幅 x 高さ x 画素のバイト数(1, 3, 4) の値がint型の最大値に引っかかっているようです。

 

AllocCoTaskMemの最大値

あまり使う機会はありませんが、メモリ確保で使われるAllocCoTaskMemについても調べてみました。

var ptr = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(2147483647);

こちらは、AllocCoTaskMemの引数がint型のため、最大値を超えるとビルド時にエラーとなります。

 

まとめ

C#のメモリの最大値について調べてみましたが、おおむね2GBの制限があります。

メモリのサイズというより、要素数のint型の最大値(2,147,483,647)を超える事によりエラーになっているようです。

今時のPCで、2GBしかメモリを確保できないだなんて。。

1つのプロセス(実行しているプログラム)で2GB以下のメモリを複数確保する事は可能です。

どうしても2GB以上のメモリを確保したい場合は、メモリを分割して処理するか、C言語ライブラリを作成して、メモリ管理をライブラリ側で行う事で可能になります。
ただし、この時にも、うっかりint型で width * height * ch みたいな計算をしてしまうと、int型の最大値を超えてしまうので、要素数やメモリサイズを計算するときの型には注意が必要です。

 

参考

https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/builtin-types/integral-numeric-types

 

【OpenCV/Python】ドキュメントの場所

OpenCVの公式ホームページは以下の場所になります。

Home

 

Pythonに関する情報は、まだ少ない気もしますが、各関数のマニュアルは下記のページから参照します。

https://docs.opencv.org/4.5.5/

 

各関数の引数や戻り値は、使用するOpenCVのバージョンによっても異なる場合があるので、参照する前にバージョンを使用するバージョンに合わせてください。

 

調べたい関数名が分かっている場合は、右上の検索ボックスに関数名を入力すると、関数候補が表示されるので、その関数をクリックします。

 

Pythonに関する情報は、ちょっと少ない気もしますが、引数の数や順番などは確認できます。

 

日本語のドキュメントが見たい場合には、最近の更新がありませんが、もともとあったOpenCV-Pythonのチュートリアルのページ(現在は閉鎖されています)を翻訳してくれたページがあるので、こちら↓が参考になります。

http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_tutorials.html

こちらのページは情報が古くなっているので、本家のページと合わせて参照すると良いかと思います。

【PyTorch】既存モデルをONNXに保存しC#で推論する方法

DeepLearningのプログラムは、ほとんどがPythonで書かれる場合が多いのですが、画像入力やGUI部分をプログラムしたいとなると、やっぱりC#で組みたい!

ということで、学習まではPythonで行い、学習結果をONNXに保存し、ONNXをC#から読み込んでC#で推論を行う方針で、いろいろ調べてみたのですが、分からない部分もボロボロと...

とりあえず、出来た事のメモです。

 

作成したプログラムのイメージ

今回は.NET Coreを使って作成していますが、.NET Frameworkでも大丈夫です。

PyTorchで既存モデルをONNXファイルに保存

今回は、画像認識モデル(Object Detection)をONNXファイルに保存するサンプルです。

入力画像サイズや出力の名前を使用するモデルに合わせる必要があります。

import torch
import torchvision

# 入力画像サイズ(N, C, H, W)
x = torch.randn(1, 3, 480, 640)
# 学習済みモデル
# 参考 https://pytorch.org/vision/main/models.html#object-detection-instance-segmentation-and-person-keypoint-detection
model = torchvision.models.detection.fasterrcnn_mobilenet_v3_large_320_fpn(pretrained=True)

# ONNXファイルに保存
# 参考 https://pytorch.org/docs/stable/onnx.html
torch.onnx.export(
    model,                                          # ニューラルネットワークモデル
    x,                                              # 入力データ
    'fasterrcnn_mobilenet_v3_large_320_fpn.onnx',   # ONNXファイル名
    opset_version=11,                               # ONNXバージョン
    input_names = ['input'],                        # 入力の名前
    output_names = ["boxes", "labels", "scores"]    # 出力の名前
    )

input_names と output_names の指定は省略可能です。

C#でONNXファイルを読み込み、推論を行う方法

C#でONNXを扱えるライブラリは、いくつかあるようなのですが、今回は、マイクロソフトのOnnxRuntimeを使いました。

フォームにはボタン(button1)とピクチャボックス(pictureBox1)のみを配置しています。

使用には、NuGetでMicrosoft.ML.OnnxRuntimeを追加する必要があります。

分かっていない部分

以下は、私が分かっていない部分なので、出来るかも?しれません。

  • OnnxRuntimeで読み込めるONNXのバージョンは10まで?らしいのですが、PythonでONNXのバージョンを10で保存できない。
    ニューラルネットワークのモデルにも依存すると思いますが、詳細は分からず...
  • ONNXファイルに保存するとき、ワーニングがいっぱい出てる。
  • 自前でモデルの学習を行うと、C#側で正しく推論できない。
  • C#でGPUを使った推論方法が分からない。
  • C#で画像をテンソル(floatの一次元配列)に変える部分は自作しましたが、下記のページを見ても、いまいちわからず。
    https://docs.microsoft.com/ja-jp/dotnet/machine-learning/tutorials/object-detection-onnx

参考

https://pytorch.org/vision/main/models.html#object-detection-instance-segmentation-and-person-keypoint-detection

https://pytorch.org/docs/stable/onnx.html

https://docs.microsoft.com/ja-jp/windows/ai/windows-ml/tutorials/pytorch-convert-model

https://docs.microsoft.com/ja-jp/windows/ai/windows-ml/get-started-uwp

https://docs.microsoft.com/ja-jp/dotnet/machine-learning/tutorials/object-detection-onnx

 

【Windows11】最近使用したファイルをすべて削除する方法

エクスプローラーでクイックアクセスに表示される最近使用したファイルは、完全にプライベートで使うPCの場合はあってもいいのですが、共有PCだったり、エクスプローラの画面をプロジェクタに表示する場合など、表示させたくない場合もあります。

その時に、ファイル一つ一つを消すには、消したいファイルを右クリックし、クイックアクセスから削除をクリックすれば最近使用したファイルから削除することができますが、消しても消しても古いファイルが表示され、すべてを消すのは大変です。

そこで、最近使用したファイルをすべて削除するには、エクスプローラーの右上に表示されている(もっと見る)をクリックし、オプションを選択します。

表示されたウィンドウのプライバシー消去をクリックします。

これで、最近使用したファイル内のファイル一覧がすべて削除されます。(ファイルの実態は残っています。)

そもそも最近使用したファイルを表示させたくない場合は、プライバシー内の最近使ったファイルをクイックアクセスに表示するのチェックを外します。

 

ただ、私のPC(Windows11 Home 21H2)ではエクスプローラのオプションを表示するとエクスプローラが何も操作できなくなりました。

しょうがないので、新規にエクスプローラを立ち上げ、もう一度オプションの表示をすると、オプションの画面を操作することができるようになりました。

Pythonプログラムのexe化

Pythonで作ったプログラム(*.pyファイル)は、Pythonの実行環境と、使用したモジュールがインストールされた環境でないと実行できないため、他のPCでプログラムを実行するのが面倒だったりもします。

PyInstallerというのを使うと、Pythonプログラムをexeにして実行することが可能になります。

私自身は、普段からVisual Studio2019を使って開発しているので、Visual StudioからPyInstallerを使う方法を紹介します。(おそらくVisual Studio2017以降であれば同様の操作で出来ると思います。)

Python環境の作成

Visual StudioのソリューションエクスプローラーPython環境を右クリックし、環境を追加をクリックします。

表示された画面の仮想環境を選択し、名前の部分に適当な名前を付け(今回はexeにしました)、ベースインタープリターの部分で、もともと使っていたPythonの環境(バージョン)を選択し、右下の作成をクリックします。

すると、今回作成した環境(exe)が追加されます。

ただし、パッケージ(PyPI)の部分を見ると、必要なモジュールが何もインストールされていない状態になります。

今回の例では、exe化しようとしているPythonファイル(*.py)は、pillowとnumpyを使用するため、別途、作成したPython環境(exe)に必要なモジュールをインストールする必要があります。

モジュールのインストールはPyPIとインストールされたパッケージの検索の部分に必要なモジュール名を入力すると、次のコマンドを実行する:pip install Pillow が表示されるので、この部分をクリックして、モジュールをインストールします。

各自、必要なモジュールは異なりますので、この状態で、Pythonのプログラムが実行できるか?確認しておいてください。

PyInstallerのインストール

exe化するためのPyInstallerも他のモジュールと同様にインストールします。

PyPIとインストールされたパッケージの検索の部分にpyinstallerと入力し、次のコマンドを実行する:pip install pyinstaller が表示されるので、この部分をクリックして、PyInstallerをインストールします。

私の場合、最終的に、このよう↓になります。

exe化の実行

PyInstallerを使ってexe化するには、コマンドプロンプトでコマンドを入力する必要があるので、コマンドプロンプトを表示します。

プロジェクトの名前の部分を右クリックし、表示されたメニューのここでコマンドプロントを開くをクリックします。

すると、プロジェクトのフォルダがコマンドプロンプト上に表示されます。

ここに、以下のコマンドを入力します。

pyinstaller [pyファイル名]

私の場合は以下のようにしました。

このコマンドを実行すると dist というフォルダが作成されます。

distフォルダの中にさらにプロジェクト名のフォルダが作成され、さらに、この中に目的とするexeファイルが作成されています。

他のPCでexeファイルを実行するには、exeファイルと同一階層にあるファイルすべてが必要になります。

ファイルがいくつも出来てしまうのは、少々扱いが面倒なので、必要なファイルも含めてexeファイル一つにすることもonefileオプションを設定することで可能です。

pyinstaller [pyファイル名] --onefile

また、プログラム起動時に表示されるコマンドプロンプトのウィンドウ↓

を表示させたくない場合は、windowedオプションを指定します。

pyinstaller [pyファイル名] --onefile --windowed 

私の場合の例↓

onefileオプションを使うと distフォルダ内にexeファイルが一つだけ作成されるので、このexeファイルを別のPCに持っていくだけで、Pythonや各種モジュールをインストールすることなく、実行することができます。

ただし、使用するモジュールからさらにdllを参照している場合などは、dllのインストールが必要になるかも?しれません。

参考

https://pyinstaller.readthedocs.io/en/stable/usage.html

【Python/Pillow(PIL)】JPEG画像の品質を指定して保存する

JPEG画像の保存では、品質を指定することで、画像のファイルサイズが変わります。

品質を良くすると、画像はキレイになりますが、ファイルサイズが大きくなります。

逆に品質を下げると、画像にノイズが乗りますが、ファイルサイズが小さくなります。

JPEG画像の品質を下げたときに乗る代表的なノイズとして、ブロックノイズモスキートノイズというものがあります。

品質を指定してJPEGファイルを保存するときの構文は以下の通りです。

Image.save(jpegfilename, quality = 75)

となります。

品質の値(quality)は初期値が75で指定可能なのは、0(低品質)~95(高品質)です。

サンプル

from PIL import Image

# 画像を開く
img = Image.open("Mandrill.bmp")

# JPEGで品質を指定して画像を保存する
img.save("Mandrill_q10.jpg", quality = 10)
img.save("Mandrill_q50.jpg", quality = 50)
img.save("Mandrill_q75.jpg", quality = 75)
img.save("Mandrill_q95.jpg", quality = 95)

# 画像を開く
img = Image.open("ImagingSolution.bmp")

# JPEGで品質を指定して画像を保存する
img.save("ImagingSolution_q10.jpg", quality = 10)
img.save("ImagingSolution_q50.jpg", quality = 50)
img.save("ImagingSolution_q75.jpg", quality = 75)
img.save("ImagingSolution_q95.jpg", quality = 95)

入力画像

評価用に読み込む画像は非圧縮のビットマップファイル(*.bmp)にしました。

一つは一般的な画像としてマンドリルの画像と、もう一つはモノクロでエッジの強い文字の画像にしました。

Mandrill.bmp
256×256画素24bitカラー
196,662バイト(非圧縮)
ImagingSolution.bmp
256×256画素8bitグレースケール
66,614バイト(非圧縮)

ファイルサイズの比較

quality 画像 サイズ(バイト)
10 4,465
50 13,189
75 19,908
95 47,073
10 3,594
50 6,629
75 8,487
95 15,452

等倍の画像で見ると qualityが50以上であれば、見た目に差はさほど感じられないでしょうか?

qualityが75と95とで比較すると、特に文字の画像を見ると、ほんの少しだけエッジがくっきり見えますが、ファイルサイズが倍近く異なります。

ノイズの比較

画像の中心付近を拡大して、ノイズを確認してみます。

quality = 10

quality = 50

quality = 75

quality = 95

quality = 10

quality = 50

quality = 75

quality = 95

マンドリルの画像ではquality = 50ぐらいまでが、四角いマス状のノイズ(ブロックノイズ)が確認できます。

文字の画像は、明暗の差が大きく、エッジが強い画像の代表例として用いたのですが、黒い周りにゴミのように見えるモスキートノイズが確認できます。

 

ノイズの出方やファイルサイズの両方を考えると、qualityの初期値である 75 ぐらいがバランスが良さそうです。

参考

https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.save

https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html