2014-10-31

プロ生ちゃん #カレンダープログラミング プチコンテスト 2014に応募しました

現実逃避の一環として、表題のイベント
に応募しました。カレンダー出力するだけのプログラムが対象なのでお気軽にできるかなーというのと、久しぶりにGWTで書いてみようかということでチャレンジしましたが、意外と手こずり、3時間もかかってしまいました。GWTではCalendarクラスが使えないので、代替するクラスを調べたり自作したり、、、という余計な手間がかかったのが原因です。見栄えのところは全く手付かずで、とりあえずLabelにHTML出力しただけです。ソースコードは下記の通り。

package org.ochilab.pronama.calendar.client;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.datepicker.client.CalendarUtil;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class ProNamaCalendar implements EntryPoint {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
/* GWTではCalendarクラスが使えないので変なことしてます*/
//現在の日時の入手
Date startDate = new Date();
//月初め
CalendarUtil.setToFirstDayOfMonth(startDate);
//月初めの曜日番号を求める
int dayNum = getDayNumber(startDate);
//次の月初めを求める
Date endDate = CalendarUtil.copyDate(startDate);
CalendarUtil.addMonthsToDate(endDate, 1);
//1日ずらして今月末にする
CalendarUtil.addDaysToDate(endDate, -1);
//今月の日数を求める
int daysBetween = CalendarUtil.getDaysBetween(startDate, endDate);
daysBetween+=2;
SafeHtmlBuilder shb = new SafeHtmlBuilder();
int index;
for(index=0;index<dayNum;index++){
shb.appendHtmlConstant("-- &nbsp;");
}
for(int i=1; i<daysBetween;i++){
if(index%7==0){
System.out.println("");
shb.appendHtmlConstant("<br>");
}
String s = NumberFormat.getFormat("00").format(i);
shb.appendEscaped(s+" ");
index++;
}
//とりあえずLabelに出力
HTML label = new HTML(shb.toSafeHtml());
RootPanel.get("nameFieldContainer").add(label);
}
/**
*
* GWT では Calendarクラスが使えないので。。。。
* @param day
* @return
*/
private int getDayNumber(Date day){
DateTimeFormat fmt = DateTimeFormat.getFormat("EEE");
Map<String, String> map = new HashMap<String,String>();
map.put("Sun", "0");
map.put("Mon", "1");
map.put("Tue", "2");
map.put("Wed", "3");
map.put("Thr", "4");
map.put("Fri", "5");
map.put("Sat", "6");
String temp = fmt.format(day);
return Integer.parseInt(map.get(temp));
}
}


Windows2008 Serverの時刻を合わせる

おちラボでは研究室内でWindows2008 Serverを立ち上げて、ドメインの構成をしています。ドメイン内のクライアントPCの時刻は、PDCのNTPサーバ機能(Time Server)によりPDCと同期することになっています。しかし、PDCの時間が間違っているとすべてのPCの時間がおかしくなります。ラボ内でもそういう事象になっていたので、PDCの時間を外部のNTPサーバーに同期しようとしたのですが、PDC(Windows 2008 Server)にはGUIでの設定画面がありません。
そこで、以下の手順で環境確認&設定しましょう。

現在の設定の確認
> w32tm /query /status
と入力すると、現在の時刻同期の設定が見れます。ソースの箇所で同期元が確認できます。おそらく「Free-runnnig System Clock」となっているハズです。つまり、マザーボードの時間(システム時間)と同期しています。

外部NTPサーバの利用
> w32tm /config /manualpeerlist:ntp.nict.jp,0x8 /syncfromflags:manual /reliable:yes /update
と入力すると、設定できます。上記ではNICTのNTPサーバに接続しています。コマンドが正しく完了されたら、もう一度上記のコマンドで設定を確認しましょう。NICTのサーバになっていると思います。

これで、研究室のPCの時刻も正しく時を刻むようになりました。本記事は下記のサイトを参考にしました。ありがとうございます。


2014-10-30

C#にて「InitializeComponent は現在のコンテキスト内に存在しません」というエラーが出た場合

表題にあるようなエラーメッセージが出てしまった場合は、
  • Namespaceの情報に齟齬が起きている
というケースがほとんどです。よくあるのが、書籍やネットのサンプルプログラムを書き写した時に、Namespaceの記述まで書きなおしてしまったという事例です。Namespaceのことを理解していない初心者にありがちなミスです。プロジェクトのデフォルトのNamespaceに戻しましょう。


2014-10-23

WPFにてウィンドウを透明化する

透明なウィンドウを実現するには、Xaml側のファイルにてプロパティを下記のように書けばOK。
  • WindowStyle="None" 
  • AllowsTransparency="True" 
  • Background="Transparent"
ウィンドウの上に何も載せないと実行時に何も見えないので注意。また、透明化するとクリックイベントも拾ってくれなくなるのでこれも注意。
<Window x:Class="TransparentForm.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowStyle="None" AllowsTransparency="True" Background="Transparent" Title="MainWindow" Height="167" Width="443" Loaded="Window_Loaded">
</Window>


2014-10-15

相互運用型 'Shell32.ShellClass' を埋め込むことができません

表題のようなエラーが出た時は、Shell32プロパティにて、
  • 「相互運用機能型の埋め込み」をFalse
にすることで解決します。

2014-10-14

WriteableBitmap を使用する場合の参照の追加について

独自作成のクラスライブラリ等でWriteableBitmap(System.Windows.Media.Imaging)を使うときは、
  • PresentationCore
という.NETコンポーネントを参照に追加しましょう。


2014-10-10

KinectにてColorFrameに対応するDepthFrameのPlayer情報を入手する方法

KinectではDepthカメラとColorカメラに座標のズレが有るため、v1.6から下記の座標変換系のメソッドがあります。(Kinect.CoordinateMapperクラスより)
  • MapColorFrameToDepthFrame 
  • MapColorFrameToSkeletonFrame 
  • MapDepthFrameToColorFrame 
  • MapDepthFrameToSkeletonFrame
  • MapDepthPointToColorPoint 
  • MapDepthPointToSkeletonPoint  
  • MapSkeletonPointToColorPoint 
  • MapSkeletonPointToDepthPoint
しかしこれはよく見ると、ColorPointから変換するメソッドがありません。つまり、Colorイメージのある座標をとることができない?実は、MapColorFrameToDepthFrameを利用すれば変換できるんですが、このメソッドで出力されるDepthImagePointについては、
  •  DepthImagePointクラスではPlayerIndexがとれない。(Depthはとれる)
という訳の分からない仕様になっています。ですので、一般的にはPlayer情報を取ってくるには、DepthImageのループから該当する箇所のColorImage座標を取ってくるという手法が取られてます。しかし、逆のことがしたいことってあるはずです。

解決策は、前記事にヒントがあります
つまり、ColorImageに合わせたマスクをあらかじめ作っておくことで、任意の座標からPlayer情報の有無を呼び出すことが可能です。実は前記事は、画像のマスクとした扱えるように2値化してますが、もっとシンプルな形式で保存しても構わないと思います。


Kinectにてユーザ領域のマスク(WriteableBitmap)を生成する

よくあるテキスト等で書かれている処理ですが、ユーザ領域のマスクを作っておくと、後々便利なことがあったりしますので、、、、
public WriteableBitmap createPlayerMaskWBitmap(DepthImagePixel[] depthImagePixels, ColorImagePoint[] colorImagePoints) {
int width = KINECT.DepthStream.FrameWidth;
byte[] outputColor = new Byte[KINECT.ColorStream.FramePixelDataLength];
WriteableBitmap testBitmap = new WriteableBitmap(colorFrameWidth, colorFrameHeight, 96, 96, PixelFormats.Bgr32, null);
for (int i = 0; i < depthImagePixels.Length; i++) {
int colorIndex = ((colorImagePoints[i].Y * width) + colorImagePoints[i].X) * 4;
if (depthImagePixels[i].PlayerIndex != 0) {
outputColor[colorIndex] = 255;
outputColor[colorIndex + 1] = 255;
outputColor[colorIndex + 2] = 255;
outputColor[colorIndex + 3] = 0;
} else {
outputColor[colorIndex] = 0;
outputColor[colorIndex + 1] = 0;
outputColor[colorIndex + 2] = 0;
outputColor[colorIndex + 3] = 0;
}
}
testBitmap.WritePixels(ColorImageBitmapRect, outputColor, ColorImageStride, 0);
return testBitmap;
}


2014-10-06

OpenCVSharpにてMatを利用してピクセルのRGB値を変更する(ポインタ利用編)

以前の記事で
というのを書きましたが、あれはダメですね。遅すぎです。C#でもポインタは使えますので、下記のように書けばOKです。

unsafe {
byte* b = mm.DataPointer;
for (int i = 0; i < height; i++) { //for文は1つにまとめていいんだが
for (int j = 0; j < width; j++) {
b[0] = 255; //B
b[1] = 255; //G
b[2] = 255; //R
b = b + 3;
}
}
}