Hatena::Diary

takminの日記

2010-01-29

これから社会に出る学生へのアドバイス

| 19:55

若者に説教垂れるようになったら立派なオッサンだというのは自覚しつつも・・・

「就職人気トップは「公務員」 安定志向を反映」(J-CASTニュース)

これを見てちょっと思うところがあったので、リストラ経験者の僕からアドバイスをしたい。

常に自分の市場価値を意識しよう

みんな安定が欲しいから、血眼になって大企業公務員を目指すんだろうけど、終身雇用がほとんどなくなっちゃった今、リストラっていうのは誰にでも起こり得る問題なんじゃないかって僕は考えている。

僕が新卒入社した会社は外資系ではあったんだけど、日本法人は今まで一度も首切してないって豪語してた。不景気が始まった頃は従業員の給与カットなどで頑張って雇用を維持しようとしていたみたいだけど、長引く不況でそれも限界を迎えて、ついにリストラに踏み切った。で、一度リストラが始まったら後はもう歯止めが効かなくなったのか、以後も定期的にリストラが入るようになって、従業員の数はどんどん減ってくし、お陰さまで僕も職を失いました。

なので、大企業に入ったからって安心せずに、いざって言うときは転職できるんだって心構えを持っておくのはとても大事だと思ってる。確かに転職リスクだ。アメリカみたいに転職を重ねることでキャリアを積んで年収が上がるっていうのは日本ではなかなかない。むしろ年収は転職を重ねた方が下がる。(僕みたいに)

でも、転職しないリスクっていうのも存在する。今の会社でいくら頑張っても自分のスキルとか経験とかが積めず、ルーチンワークを何年も続けることが見えているなら、それはリスクだ。転職市場では、同じスキルセットを持っているなら当然のことながら若い人間の方が有利だし、悲惨なのはその会社にしがみついて大したスキルアップもできないまま、歳をとってからリストラされるというパターン。ましてや、今は昔みたいに会社に長く勤めれば必ず給料が上がるわけでもない。

だから、常に自分が他の会社でも通用する人間か、自分の労働者としての市場価値はどうかというのは意識した方が良い。そして、今いる会社で市場価値を高めるための努力をし、それがどのような手を尽くしても上がらないと感じたなら、例え給与が下がるとしても転職を一つの選択肢とするべきだと思う。

それと、いつでも転職できる状態と言うのは、いわば会社と対等な雇用関係にあるということでもあるし、精神的な自由を手にいれることでもある。もし会社が不正を働いていて自分がそれに巻き込まれそうになったら?もし上司のビジネスのやり方がまずくて、いずれトラブルを起こしてその火の粉が自分にかかることがわかっていたら?精神的な自由は、自分が正しいと信じる生き方を貫くためにも重要なんだ。

そして長い目で見れば、従業員が自立していると言うことは会社にとってもプラスに働くはずだ。(が、その理由は長くなるのでここではしない。)

昔、小学校の先生が「なんでイジメを見かけたのに止めないんだ」みたいなことを言ってたことがあったけど、イジメを止めようとすれば自分がいじめられるわけで、その勇気っていうのはなかなか持てるものじゃない。でも精神的な自由は、その時にイジメを止めに入る勇気をくれる。



最初にどんな職種につくか、は結構大事

日本の企業はどういうわけか、新卒社員が大学時代どんな専門性を身につけてきたかというのはあまり重要視しない。僕が入社した会社は理工系修士卒の人間を営業に回したりしていた(僕もあやうく営業にまわされるところだった)。

入社する時点でだいたいどの部署でどんな仕事をするって決まっている場合もあるけど、会社によってはあまりそこら辺細かく決まってなくて、新入社員研修の後決めて行くようなところもある。

で、最初に入った会社でどういう仕事につくかと言うことが、どんな会社に入るか以上に自分の人生のその後を大きく左右する。例えば僕は元々開発職を希望していたんだけど、実際は営業の技術サポートに回された。そして4年半後にリストラされた後、開発職につこうとあちこち応募してみたけど、開発経験がないということで片っ端から断られた。(最終的にはほとんど従業員がいないようなベンチャー企業に拾われたけど)

新卒入社では、それまで何を勉強したかと言うのをあまり問われないけど(それはそれでどうかと思うけど)、一度社会人になったら第二新卒でもない限り、どんな仕事をしてきたのかという経験は大きく問われる。今までのことは辞めて別の全く新しいことに挑戦するっていうのは、サラリーマンではかなり難しい。だって転職の時に採用する側は、即戦力が欲しいわけだから、やる気があっても能力があるのかどうかわからないような人材は怖くて雇うことはできない。

なので、ある程度やりたい事が見えている人は、会社の規模にこだわるよりもやりたい事にこだわって会社を選んだ方が良い。またもしその会社が入社後に配属を決めるようなシステムで、希望を聞かれたなら「別にどんな部署でも一所懸命働きます」と言うよりもちゃんと希望を伝えた方が良い。

ただし大企業に入るメリットとして、大企業ならではの組織運営の仕方と言うのを中から見ることができるのは大きな利点だ。大企業から中小企業ベンチャーへの転職は容易だけど、逆のパターンの転職は実際のところ難しい(その人が残した実績によってはもちろん可能ではあるけど)。だから、同じ仕事内容で新卒として大企業ベンチャーとどっちを選んだら良いか?と相談されたら、僕は大企業を勧める。


仕事の本質は人の役に立つこと

仕事っていうのは、お金を稼ぐことが大事なのは確かだし、それゆえ安定志向になるのは理解できる。でも、考えて欲しいのは、なぜお金を稼ぐことができるのかということ。

例えば企業はモノを売る。お客さんはそれを買う。なぜお客さんがそれを買うのかというと、それが自分の役に立つものだと判断したからだ。そのお客さんが払ったお金というのが回りまわってあなたのお給料になる。

例えばあなたの仕事が、毎日が雑用ばかりでつまらないと思うかもしれない。でもその雑用の御陰で、他の人が自分の仕事に専念できて、それが結果としてお客さんのためになり会社の利益になる。

だからこそ、職業に貴賎なしだと僕は思っている。お金をもらえるのは誰かに必要とされているからなんだ。

で、前のところで「自分の市場価値を意識しろ」とか「最初にどんな職種につくかは結構大事」って言ったけど、これはある程度その後の努力で選択する立場になれる人間に向けた言葉になっている。でも実際は自分が何やりたいのかもわからず、どういう方向にスキルをつけていいのかもわからず、ただ日々生きてお金を稼ぐのに精一杯という人もたくさんいるだろう思う。そんな時、夢を持って仕事をしてないことを悲観する必要はまったくないんだ、ということは言っておきたい。

昔読んだ「絶望に効くクスリ」というインタビュー漫画の中で養老孟司が語っていた仕事観が印象に残っている。記憶が曖昧なので台詞は正確ではないと前置きしつつ、「仕事っていうのは道に空いた穴を埋めるようなもの。自分の好き嫌いではなく、後を通る誰かの役に立てればそれでいい」みたいなことを言っていて、まさにこれこそ仕事の本質なんじゃないかと思う。

公務員でもその本質は一緒。民主主義社会で、なぜ国民が税金を収めるかというと、それをもとに自分達の生活を豊かにするための行政サービスを受けるためだ。「安定するから」とか「家族が喜ぶから」も大事だが、それを一番の動機にして欲しくない。自分のやっていることが回りまわって、サービスを受けている住民たちの幸せに寄与しているんだという意識を強く持って欲しい。

何を当たり前なことをと思うでしょう。でもここに書いたことって、上司のプレッシャーやら株主のプレッシャーやら納期のプレッシャーやらにさらされているうちに高い確率で忘れると思う。


以上がオジサンからのアドバイスです。

まあ、僕自身が人生をさまよっている最中なので、あんま偉そうなこと言える立場じゃないんだけどね。(笑)

2010-01-08

OpenCV2.0におけるファイル保存機能の使い方

| 17:07

OpenCV2.0のC++インターフェースにおいて、クラスや構造体の永続化の関数XML/YAML Persistence)が、1.1のそれと色々変わったのでメモ。2.0のファイル保存機能に関してはまだまだドキュメントも書籍も乏しい状態なので、ソースを眺めてわかったやり方などもひっくるめて書いておく。

まずは、以下に1.1の場合と2.0の場合のファイル保存のサンプルを書く。

ここでは、int型、float型、CvMat型の配列をそれぞれ保存する方法についての例。

1.1の場合

	char filename[] = "save_cv.xml";	// file name

	////// creating data for save //////////////
	int a = 10;
	float b = 0.1;
	CvMat** mat = (CvMat**)malloc(3*sizeof(CvMat*));
	for(int i=0;i<3;i++){
		mat[i] = cvCreateMat(3,3,CV_32FC1);
		cvSet(mat[i], cvScalar(i));
	}
	////////////////////////////////////////////

	// Open File Storage
	CvFileStorage *cvfs = cvOpenFileStorage(filename,NULL,CV_STORAGE_WRITE);

	cvWriteInt(cvfs,"a",a);
	cvWriteReal(cvfs,"b",b);

	cvStartWriteStruct(cvfs, "mat_array", CV_NODE_SEQ);		// create node
	for(int i=0; i<3; i++){
		cvWrite(cvfs,NULL,mat[i]);
	}
	cvEndWriteStruct(cvfs);

	// Close File Storage
	cvReleaseFileStorage(&cvfs);

	// release mat
	for(int i=0; i<3; i++){
		cvReleaseMat(mat+i);
	}
	free(mat);

2.0の場合

	char filename[] = "save_cv2.0.xml";	// file name

	////// creating data for save //////////////
	int a = 10;
	float b = 0.1;

	cv::Mat mat[3];
	for(int i=0; i<3; i++){
		mat[i].create(3,3,CV_32FC1);
		mat[i].setTo(cv::Scalar(i));
	}
	////////////////////////////////////////////

	// Open File Storage
	cv::FileStorage	cvfs(filename,CV_STORAGE_WRITE);

	cv::write(cvfs,"a",a);
	cv::write(cvfs,"b",b);
	cv::WriteStructContext ws(cvfs, "mat_array", CV_NODE_SEQ);	// create node
	for(int i=0; i<3; i++){
		cv::write(cvfs,"",mat[i]);
	}

保存されるファイルは、1.1、2.0とも同じで、こんな感じになります。

save_cv.xml

  <opencv_storage>
  <a>10</a> 
  <b>0.1000000014901161</b> 
  <mat_array>
  <_ type_id="opencv-matrix">
  <rows>3</rows> 
  <cols>3</cols> 
  <dt>f</dt> 
  <data>0. 0. 0. 0. 0. 0. 0. 0. 0.</data> 
  </_>
  <_ type_id="opencv-matrix">
  <rows>3</rows> 
  <cols>3</cols> 
  <dt>f</dt> 
  <data>1. 1. 1. 1. 1. 1. 1. 1. 1.</data> 
  </_>
  <_ type_id="opencv-matrix">
  <rows>3</rows> 
  <cols>3</cols> 
  <dt>f</dt> 
  <data>2. 2. 2. 2. 2. 2. 2. 2. 2.</data> 
  </_>
  </mat_array>
  </opencv_storage>

以下、この例での変更点を列挙する。

  • 1.1ではCvFileStorageという構造体を用いて、データの保存などを行っていたのが、2.0からcv::FileStorageクラスに変更になった。ただし旧来のCvFileStorage構造体のポインタ引数として渡すことでFileStorageクラスを作成することも可能。2.0から新たに導入された各種クラスや構造体(例えばKeyPoint構造体)などは、やはり2.0用の永続化関数を使用しないと保存できない。
  • 基本的なファイル構造の考え方は、1.1以前のそれと一緒で、ファイルの中の論理構造は木構造になっている。1.1ではCvFileNodeという構造体が各木のノードを表していたのが、2.0からFileNodeというクラスに変更になった。(後述)
  • 書き込み時にノードを新たに作成する場合、1.1では"cvStartWriteStruct()"、"cvEndWriteStruct()"という関数を使って書き込みノードの間を囲ってやる必要があったが、2.0からはWriteStructContextクラスを生成することでノードを作成して開き、このクラスを開放(デストラクタ呼び出し)を行うことで、ノードを閉じる。(尚、ノード配列などの連続値を保存したいときは引数に"CV_NODE_SEQ"を指定し、構造体を保存したい場合は"CV_NODE_MAP"を使用するという点はどちらのバージョンでも同じ)
  • 1.1ではデータの型ごとに"cvWriteInt()"や"cvWriteReal()"という形で使い分けていたが、2.0からは全て"cv::write()"関数に統合された。
  • 2.0から、ファイル保存時に拡張子".gz"で保存すると、圧縮して保存してくれるようになった。

では次に、読み込みの例

1.1の場合

	////// creating data for save //////////////
	int a;
	float b;

	CvMat** mat = (CvMat**)malloc(3*sizeof(CvMat*));
	////////////////////////////////////////////

	// Open File Storage
	CvFileStorage *cvfs = cvOpenFileStorage(filename,NULL,CV_STORAGE_READ);

	CvFileNode* node = cvGetFileNodeByName(cvfs,NULL,"");	// Get Top Node

	a = cvReadIntByName(cvfs, node, "a");
	b = cvReadRealByName(cvfs, node, "b");

	CvFileNode* fn = cvGetFileNodeByName(cvfs,node,"mat_array");

	CvSeq *s = fn->data.seq;
	int total = s->total;
	for(int i=0;i<total;i++){</pp>
		mat[i] = (CvMat*)cvRead(cvfs,(CvFileNode*)cvGetSeqElem(s,i));
	}
	// Close File Storage
	cvReleaseFileStorage(&cvfs);

2.0の場合

	////// data for load //////////////
	int a;
	float b;
	cv::Mat mat[3];
	////////////////////////////////////////////

	// Open File Storage
	cv::FileStorage	cvfs(filename,CV_STORAGE_READ);

	cv::FileNode node(cvfs.fs, NULL);	// Get Top Node
	a = node["a"];
	b = node["b"];
	cv::FileNode fn = node["mat_array"];
	
	for(int i=0;i<fn.size();i++){</pp>
		cv::read(fn[i], mat[i]);
	}

違いは、

  • 1.1では読み込む型によって例えば"cvReadInt"や"cvReadReal"という形で関数が用意されていたが、2.0ではFileNodeクラスに[]でノードの名前を添字してやれば値が取得できる。ただし、OpenCV定義のクラスや構造体を読み込むときは、"cv::read()"を利用する。
  • 1.1では連続したデータに対して、CvSeq構造体に一度ノードの情報を格納してアクセスする必要があったが、2.0ではやはりFileNodeクラスに番号を添字してやれば良い。

以上。

2010-01-01

20%ルールの合理性

| 19:22

Twitter使い出してから、あまりこちらのブログにつぶやき系を書かなくなったんだけど、以前つぶやいた内容を再掲しておく。

------

実は新しい物を作っていく上でGoogleの20%ルールのうちの残りの80%の通常業務がかなり大事なのではないかという気がしている。その80%で研究開発技術者が直接ビジネスニーズを知ることが出来るから。

------

実は、日本の大企業のR&Dって(もちろん企業にもよるけど)かなり自由にやれている印象がある。会社の承認は必要だけど、自分たちである程度自由にテーマを選定して、それに対して100%の時間を使って研究をしているんじゃないかと思う。

ただ、これらの大企業は多大な投資をして、良い技術開発をしている割に、いまいちビジネス化がヘタなんじゃないかと感じている。

で、先のつぶやき「実は80%が大事」という考えに至ったわけです。

これは、研究開発から製品化までのスパンの短い情報系では特に言えることなんじゃないだろうか。特に情報系のコンシューマビジネスでは、開発エンジニアが直でユーザの反応に接する機会も多いだろうから、なおさら敏感にニーズを感じることができる。

また、R&Dから生まれた研究を製品化するという点においても、20%ルールには合理性がある。

情報系の学問では、論文や学会などで良い結果が出てたとしても、じゃあどこかのプログラマーがその論文通りに実装して同じ結果がでるかというと、実はとても難しい。というのは、その論文で実装しているプログラムの中には、論文に書かれていない色々なパラメータや工夫が隠されていることがほとんどだから。

そうなると、一番良いのはそれを研究した本人が製品化の実装まで担当することだと思う。つまり、研究者として優れているだけでなく、プログラマーとしても優れていることが、ITの世界で革新的なサービスや製品を創り上げて行く上で大事になってくる。でも、通常の企業だと研究をする人と開発する人というのは分かれている場合がほとんど。でも20%ルールの場合、その中で作ったものが有益で「業務」として認められれば、研究者は今度は実装者として80%の面倒がみれる。

そして、まさにこういう研究者兼実装者を抱えているのがGoogleじゃないだろうか。

さて、この20%ルールをワーカホリックな日本の労働環境でどうやって作り出すかというのは、考えてみると難しい。大抵の場合、20%の空きなんて作れないし、20%のクリエイティビティを発揮すべき優秀な人間には、仕事が集中する仕組みになっているから。

で、これに関しては僕にはアイデアはない。ただ企業は、もし100%のR&Dという組織を作る資金的余裕があるのなら、その分業務に人を増やすことで、各々の従業員が20%ルールを実現できるような環境を整えるのは面白いかもしれない。


以上、まったくの独断と偏見と思い込みの記事なので、異論は認める。

OpenCV2.0のコンパイル 追記

| 18:23

前回の続き。

Visual C++ 2008 Express EditionでOpenCV2.0を使ったアプリケーション開発をする際の注意点をいくつか。


1. コンパイルはDebugモードとReleaseモード両方で行う

前回はReleaseモードでコンパイルしたけど、開発時にDebugモードで開発を行う場合は、OpenCV2.0自体もDebugモードでコンパイルしておく必要がある。

Releaseモードで作成したライブラリ群をDebugモードで使おうとすると、色々とうまくいきません。例えば、2.0から新しく導入された画像読み込み関数のimread()がうまく動かない(画像を読み込めない)などの問題が起こります。

で、DebugモードとReleaseモードでそれぞれコンパイルするとlibファイルとdllファイルがそれぞれ作成されます。

前回の例だと、以下の場所にライブラリファイル群が作成されます。これらのファイルを適当なところにコピーしたり、開発環境からリンクしたりして使ってください。

  • Debugモードで作成されるライブラリファイル
    • C:\OpenCV2.0\VS2008\lib\Debug
      • cv200d.lib
      • cvaux200d.lib
      • cvhaartraining.lib
      • cxcore200d.lib
      • cxts200d.lib
      • highgui200d.lib
      • ml200d.lib
      • opencv_ffmpeg200d.lib
    • C:\OpenCV2.0\VS2008\bin\Debug
      • cv200d.dll
      • cvaux200d.dll
      • cxcore200d.dll
      • cxts200d.dll
      • highgui200d.dll
      • ml200d.dll
      • opencv_ffmpeg200d.dll
  • Debugモードで作成されるライブラリファイル
    • C:\OpenCV2.0\VS2008\lib\Release
      • cv200.lib
      • cvaux200.lib
      • cvhaartraining.lib
      • cxcore200.lib
      • cxts200.lib
      • highgui200.lib
      • ml200.lib
      • opencv_ffmpeg200.lib
    • C:\OpenCV2.0\VS2008\bin\Release
      • cv200.lib
      • cvaux200.lib
      • cvhaartraining.lib
      • cxcore200.lib
      • cxts200.lib
      • highgui200.lib
      • ml200.lib
      • opencv_ffmpeg200.lib

2. OpenMPの使用に関して

VC++のExpress Editionでは、OpenMPをサポートしていないため、標準のままCMakeを使って作成したライブラリを使用すると、プログラム実行時に、

「アプリケーションを正しく初期化できませんでした (0xc0150002)」

というエラーが出ます。

これを解決するために、はCMakeをする時に

ENABLE_OPENMP

のチェックを外して下さい。

2009-12-11

OpenCV2.0のコンパイル

| 00:35

よーやっと2.0に手を出しました。

以下、例のごとくコンパイル時のやっつけメモ書きです。。。

ちなみに環境はWindows XP + Visual Studio 2008 Expressです。


1. OpenCV2.0のインストール

http://sourceforge.net/projects/opencvlibrary/

から"OpenCV-2.0.0a-win32.exe"をダウンロード

ダブルクリックでインストール。

デフォルトでは、"C:\OpenCV2.0"にインストールされる。

旧バージョンでは"C:\Program Files\OpenCV"だったので、場所が変わっている。

これ以下の作業はOpenCVをコンパイルして作り直す場合の作業です。特にコンパイルいらないからすぐ使いたいという人は、"C:\OpenCV2.0\include\opencv"にインクルードパスを"C:\OpenCV2.0\bin"にライブラリパスを通せば使用できるはずです。このライブラリパスの中にはdllが準備されています。ただし私はまだ動作確認してません。


2. インストール後のセットアップ

参考:

http://opencv.willowgarage.com/wiki/InstallGuide

コンパイル方法はだいぶ変わりました。今までWindows版はVisual Studioのプロジェクトファイルが用意されてましたが、2.0からCMakeというツールを使うようになりました。尚、このCMakeを使うためにMinGWというGNU Cコンパイラが必要です。


MinGWのダウンロード

http://sourceforge.net/projects/mingw/

から"MinGW-5.1.6.exe"をダウンロードして、インストール。

インストールは全てデフォルト(つまり最小パッケージ)で行った。


CMakeのダウンロード

http://www.cmake.org/cmake/resources/software.html

から"cmake-2.8.0-win32-x86.exe"をダウンロード。

これも全部デフォルトでインストール


3. コンパイル

CMake GUIを立ち上げる。CMake GUIはスタートメニューから選択できます。

"Where is the source code:"に"C:/OpenCV2.0"を

"Where to build the binaries:"に"C:/OpenCV2.0/VS2008"を指定。

このVS2008というディレクトリは僕が勝手に作りました。

configureボタンを押して現れたダイアログの"Specify the generator for this project"の欄に"Visual Studio 9 2008"を選択

default compilerを選択して"Configure"を押下

その後、"Generate"ボタンが有効になるので(ならない場合はもう一度"Configure"ボタンを押してください)、これを押す。

すると、"C:/OpenCV2.0/VS2008\OpenCV.sln"というのができるので、これを開く。

Visual Studioが立ち上がるので、構成を"Release"にしてコンパイル。

"C:\OpenCV2.0\VS2008\lib\Release"にOpenCV2.0用のライブラリ群が作られる。

終わり。