旅行好きなソフトエンジニアの備忘録

プログラミングや技術関連のメモを始めました

【OpenCVSharp】 ヒートマップを作成する

OpenCVSharpを使ってヒートマップを描くプログラムのメモです。ヒートマップは赤⇒緑⇒青の順で遷移するため、HSV空間を使い、その後RGB空間に戻すと簡単に作成できます(OpenCVでは0が赤、60が緑、120が青に相当します)。

// 画像サイズ
const int size = 101;
// ガウス関数のシグマ
const double sigma = 20.0;
// HSVを記録する行列
var hsvMap = new Mat(new Size(size, size), MatType.CV_8UC3);
for (int i = -50; i <= 50; ++i)
{
    for (int j = -50; j <= 50; ++j)
    {
        // ガウス関数の値
        double g = Math.Exp(-(Math.Pow(i, 2) + Math.Pow(j, 2))/(2.0*Math.Pow(sigma, 2)));
        // 色相の計算(OpenCVでは0で赤、120で青)
        byte hue = (byte)(120*(1.0 - g));
        hsvMap.Set(i+50, j+50, new Vec3b(hue, 255, 255));
    }
}
// HSVをBGRに変換する
var bgrMap = new Mat(new Size(size, size), MatType.CV_8UC3);
Cv2.CvtColor(hsvMap, bgrMap, ColorConversionCodes.HSV2BGR);
// ヒートマップの保存
bgrMap.ImWrite("heatmap.bmp");
hsvMap.Dispose();
bgrMap.Dispose();

上記で出来たヒートマップが以下の写真になります。
f:id:ni4muraano:20171018215712j:plain

【WPF】 ボタンのサイズをリソースで指定する

作っているアプリケーションにボタンが沢山あるのですが、それらの幅、高さは全て共通なのでハードコーディングではなく一括管理したいと考えました。そのやり方ですが、以下の2ステップになります。

① App.xamlに以下を追加(xmlns:sysと<sys:Double ...>の三行を追加してます)

<Application x:Class="ResourcePractice.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:ResourcePractice"
             xmlns:sys="clr-namespace:System;assembly=mscorlib"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <sys:Double x:Key="ButtonWidth">100</sys:Double>
        <sys:Double x:Key="ButtonHeight">100</sys:Double>
    </Application.Resources>
</Application>


② Buttonから先程のリソースを参照する

<Button Width="{StaticResource ButtonWidth}" Height="{StaticResource ButtonHeight}"/>


ちなみにこのやり方は以下のリンクを参考にしました。

stackoverflow.com

【WPF】 続・スクリーンショットを撮り続けて動画に保存する

以前スクリーンショットを撮り続けて動画に保存する記事を書いたのですが、実はMicrosoft Expression Encoderを使えばやりたいことは出来たようです。 ni4muraano.hatenablog.com

Microsoft Expression Encoderはここからダウンロードできます。NuGetからもダウンロードできるのですが、動作させようとすると良く分からないエラーが出て結局動かすことができませんでした。結局自分は下記手順で動作させることができました。

  1. リンクからMicrosoft Expression Encoderをダウンロード・インストールして
  2. NuGetからMicrosoft Expression Encoderをインストールする

プログラムについてですが、まずスクリーンショットを撮り続けて動画に保存する部分は以下になります(System.Drawing.Rectangleを使うためにSystem.Drawingを参照に追加してください)。

// usingに追加
using Microsoft.Expression.Encoder;
using Microsoft.Expression.Encoder.ScreenCapture;

// フィールドでキャプチャーを宣言
private readonly ScreenCaptureJob _capture = new ScreenCaptureJob();

// 設定、キャプチャー開始命令
_capture.CaptureRectangle = new System.Drawing.Rectangle(0, 0, 1200, 940);
_capture.ScreenCaptureVideoProfile.FrameRate = 30;
_capture.OutputScreenCaptureFileName = @"C:\Users\MyFolder\Videos\video.xesc";
_capture.Start();

そして、以下を実行することで保存した動画をWMVにエンコーディングできます。

// Stop, Disposeしないと動画が作成されない
_capture.Stop();
_capture.Dispose();
// 作成した動画をエンコーディングする
var media = new MediaItem(@"C:\Users\MyFolder\Videos\video.xesc"); ;
var job = new Job();
job.MediaItems.Add(media);
job.OutputDirectory = @"C:\Users\MyFolder\Videos";
job.Encode();

【WPF】 BitmapSourceクラスをbitmapとして保存する

BitmapSourceクラスをbitmapとして保存する方法を探していたのですが、以下に書かれていたのでメモします。

stackoverflow.com

public void SaveBitmapSourceToFile(BitmapSource bitmapSource, string filePath)
{
    using (var fileStream = new FileStream(filePath, FileMode.Create))
    {
        BitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
        encoder.Save(fileStream);
    }
}

【WPF】 UIElement上のマウスイベントが発生しない

Imageの上にCanvasを置いて、CanvasにLineやEllipseをマウス操作を通じて描くことで、仮想的にImage上に絵を描いたように見えるようにしたいと思っています。

<Image .../>
<Canvas .../>

そこでCanvasにMouseDownイベントを付けたのですが、Canvasをクリックしても一向にMouseDownイベントが発生しませんでした。このような時の対処法がここに書かれていました。

自分の場合はリンク先に書かれている1番のやり方(CanvasのBackgroundにTransparentを指定すること)でMouseDownイベントが発生するようになりました。

はてなブログでtexの数式が上手く表示されない時の対処法

texの数式が思った通りに表示されず困っていたのですが、こちらのサイトのおかげで無事解決しました。

estrellita.hatenablog.com

【Python】 季節性分解実行時のエラーへの対処

季節性分解のやり方を調べていると、seasonal_decomposeメソッドを利用すれば良いことが分かりました。ただ、実行すると

TypeError: ‘numpy.float64’ object cannot be interpreted as an integer

というエラーが出てしまいました。

import statsmodels.api as sm

df = pd.read_csv('time_series_data.csv', index_col=0)
df = df.reset_index()
df['datetime'] = pd.to_datetime(df['datetime'], format='%Y/%m/%d')
df['y'] = df['y'].values.astype(float)
df = df.set_index(['datetime'])
# ここでエラー
res = sm.tsa.seasonal_decompose(df.values, freq=7)
res.plot()
plt.show()

このエラーはstatsmodels\tsa\filters\filtertools.pyの下記コードを

elif nsides == 2:
    trim_head = np.ceil(len(filt)/2.) - 1 or None
    trim_tail = (np.ceil(len(filt)2.) - len(filt) % 2) or None

下記のように書き換えると動作するようになりました。

elif nsides == 2:
    trim_head = np.ceil(len(filt)/2.) - 1 or None
    trim_head = (int)(trim_head)
    trim_tail = (np.ceil(len(filt)2.) - len(filt) % 2) or None
    trim_tail = (int)(trim_tail)