プログラミング」カテゴリーアーカイブ

バネ・ダンパ・斥力

なんか,前もちょっと似たプログラムを作った気がしますが,
バネ・ダンパと斥力のデモプログラムを作りました.
適当に作ったので,ときどき落ちるかもしれません.

マウス:掴む,1~6キー:リセット

プログラム自体はすぐできたんですが,ブラウザで実行するとやたら遅かったので原因を調べたところ,どうやらメモリ確保がボトルネックになっていたみたいだったので,インスタンスを使いまわす汚い書き方に修正しました.processingってなんかお洒落なんでモダンな感じにプログラミングできるかと思ったんですが,意外と芋っぽいですね.実行環境の制約があるので仕方ないといえば仕方ないですが.

python in visual studio

最近良くpythonを使っているのですが,ほんのちょっとしたプログラムを書くのにはサクラエディタを,少し混んだプログラムintellisenseやエラーチェック,デバッグが便利なのでvisual studioを使っています.
それで,C++やC#を使うときのようなごてごてしたUIでpythonを使いたくはないので,python用にvisual studioのツール配置を変えていたのですが一々手作業でやるのが面倒で,eclipseのperspectiveのように,一発で配置を切り替えられる機能がないかと探してみたところ,”Perspectives”というそのままの名前のプラグインがありました.

http://visualstudiogallery.msdn.microsoft.com/addc8d85-023d-40e6-b4bc-6dc85540b711

cpp py
左:c++, c#表示  右:python表示

ほんとにeclipseのperspectiveそのままのような機能が追加でき,非常に便利です.

python3.4でmatplotlib

pythonでデータをプロットするのにmatplotlibを使っていたのですが,pythonのバージョンを3.4に上げたところ3.4には公式ではまだ対応していないらしく,インストールに非常に手こずりました.
半日GTKのライブラリを入れたりなんやら試行錯誤してもだめで諦めかけていたのですが,非公式ですが以下のサイトでpython3.4向けバイナリを配布していたので,試したところうまくいきました.
http://www.lfd.uci.edu/~gohlke/pythonlibs/

import numpy
import matplotlib.pyplot as pyplot

x = numpy.arange( -1, 1, 0.01 )
y = numpy.exp( x )

pyplot.plot(x, y)
pyplot.show()

exp_plot

なんか,無駄なことにかなり時間を消費してしまって疲れました.
そもそもなんでバージョンを上げたかったのかというと,以前まで使っていたpython2.6には誤差関数erfが定義されていなかったからなんですよね.
たしかC++でもerfはC++11まで無かったみたいで,VS2010で使えなくて驚いた記憶があります.

CamShift

ちょっとCamShiftを使った物体追跡プログラムを書いてみました.

CamShiftはMeanShiftTrackingを改良したもので,物体の大きさや姿勢の変化も追跡することができます.
触った感じだと,CamShiftの結果はRotatedRectで帰ってくるのに対して入力には通常のRectを入れなければならないので,若干扱いづらい部分がありした.RotatedRectに外接する矩形をそのまま次の初期探索領域にすると,回転によって領域が大きくなりすぎがちだったため,今回は外接する矩形を少し小さくしたものを次の初期探索領域としています.
あと,ヒストグラムにも割りと敏感なので注意してやる必要がありそうです.

ソース(VS2013, OpenCV2.4.8)

#include <iostream>
#include <opencv2/opencv.hpp>

/********************************
 * 初期矩形指定用マウスコールバック
********************************/
void onmouse(int event, int x, int y, int flags, void* userdata) {
	static bool lbutton_is_down = false;
	cv::Rect* rect = (cv::Rect*)userdata;

	switch (event) {
	case CV_EVENT_LBUTTONDOWN:
		lbutton_is_down = true;
		rect->x = x;
		rect->y = y;
		break;
	case CV_EVENT_LBUTTONUP:
		lbutton_is_down = false;
		break;
	case CV_EVENT_MOUSEMOVE:
		if (lbutton_is_down) {
			rect->width = x - rect->x;
			rect->height = y - rect->y;
		}
		break;
	}
}

/********************************
* 初期矩形設定
********************************/
cv::Rect getInitRect(const cv::Mat& frame) {
	cv::Rect init_rect(0, 0, 100, 100);
	cv::namedWindow("frame");
	cv::setMouseCallback("frame", onmouse, &init_rect);

	while (cv::waitKey(100) != ' ') {
		cv::Mat canvas = frame.clone();
		cv::rectangle(canvas, init_rect, cv::Scalar(0, 255, 0), 2);
		cv::imshow("frame", canvas);
	}
	return init_rect;
}

/********************************
 * main
********************************/
int main(int argc, char** argv) {
	cv::VideoCapture cap("mov03.mov");
	if (!cap.isOpened()) {
		std::cerr << "failed to open input file" << std::endl;
		std::cin.ignore(1);
		return 0;
	}

	cv::Mat frame, hist;
	cap >> frame;
	cv::Rect rect = getInitRect(frame);	// 初期探索矩形

	// ターゲットのヒストグラム生成
	int hist_size[] = { 64, 64, 64 };
	float range[] = { 0, 256 };
	const float* ranges[] = { range, range, range };
	int channels[] = { 0, 1, 2 };
	cv::Mat roi(frame, rect);
	cv::calcHist(&roi, 1, channels, cv::Mat(), hist, 3, hist_size, ranges);

	// メインループ, escが押されるまで
	while (cv::waitKey(66) != 0x1b) {
		cap >> frame;
		if (!frame.data) {
			continue;
		}

		// ヒストグラムのバックプロジェクション計算
		cv::Mat back_proj;
		cv::calcBackProject(&frame, 1, channels, hist, back_proj, ranges);
		// camshift
		cv::TermCriteria term_crit(cv::TermCriteria::EPS | cv::TermCriteria::COUNT, 30, 1);
		cv::RotatedRect rotated_rect = cv::CamShift(back_proj, rect, term_crit);

		// RotatedRectから次の探索矩形,boundingboxを少し小さくしたもの
		rect = rotated_rect.boundingRect();
		rect.x += rect.width / 8;
		rect.y += rect.height / 8;
		rect.width *= (6.0 / 8.0);
		rect.height *= (6.0 / 8.0);

		// RotatedRectから頂点座標
		std::vector<cv::Point2f> pts(4);
		rotated_rect.points(&pts[0]);
		std::vector<cv::Point> ptsi(4);
		std::copy(pts.begin(), pts.end(), ptsi.begin());

		// 描画
		cv::rectangle(frame, rect, cv::Scalar(255, 0, 0), 2);
		cv::polylines(frame, ptsi, true, cv::Scalar(0, 255, 0), 2);
		cv::imshow("frame", frame);
	}
}