2016年1月20日水曜日

mt_yrangemask

お久しぶりです。

potatosubさんのブログ読んでたら、yrangemaskなるフィルタを使っているのに気づきました。

わたくし、このフィルタはこれまで知らなかったんですが、ちょっと気になったことがあったので実験してみました。

#test.avs
LoadPlugin("yrangemask.dll")
LoadPlugin("masktools2.dll")

#1920x1080のグラデーション画像10000フレーム
BlankClip(length=10000, width=1920, height=1080, pixel_type="YV12")
mt_lutspa(mode="relative", expr="x 256 *", chroma="128")

#yrangemask(16, 4, 80, 16, true)
mt_yrangemask(16, 4, 80, 16, true)

function mt_yrangemask(clip clip, int "min_y", int "fade_min_y", int "max_y", int "fade_max_y", bool "invert")
{
    assert(clip.IsPlanar(), "clip is not planar format")
    min = default(min_y, 0)
    max = default(max_y, 0)
    assert(min >= 0 || min < 256 || max < 256, "Specify in the range from 0 to 255")
    assert(min <= max, "min_y must be less than or equal to max_y")
    fmin = default(fade_min_y, 0)
    fmax = default(fade_max_y, 0)
    assert((fmin + fmax) <= (max - min), "'fade_min_y + fade_max_y' should be less than or equal to 'max_y - min_y'")

    min = string(min - 1)
    max = string(max + 1)
    fmin = string(fmin + 1)
    fmax = string(fmax)
    invert = default(invert, false)

    #expr = 255 / (x < max - fmax ? fmin / (x - min) : (fmax + 1) / (max - x))
    #expr = invert ? 255 - expr : expr
    expr = "255 / (x < " + max  + " - " + fmax + " ? " + fmin + " / (x - " + min + ") : (" + fmax + " + 1) / (" + max + " - x))"
    expr = (invert ? "255 - " : "") + expr

    return clip.mt_lut(mt_polish(expr), chroma="0")
}
で、
$ for i in {1..3}; do avs2pipemod -benchmark test.avs; done

     yrangemask   mt_yrangemask 
 1   303.556fps    889.047fps
 2   300.232fps    890.155fps
 3   301.298fps    891.027fps
------------------------------------
avg  301.695fps    890.076fps

やはり気のせいではなかったようです。

mt_lutは起動時にあらかじめxが0から255までの256パターンの計算を行いLUT(ルックアップテーブル)を作るため、実行中の処理スピードは式がどれだけ複雑になっても変わりません。
LUTのサイズは256バイトですから、L1キャッシュに収まるため高速です。
逆ポーランド記法もmt_polishを使えば覚えなくて済むので、積極的に使ってみることをお勧めします。

追記:2016/01/21 mt_lutの式を簡略化 & invert=trueの場合をちょっと高速化

2015年9月12日土曜日

YV12To422 その3

YV12To422を更新しました。

YV12To422
YV12To422-1.0.2.zip

PlanarToolsのほうで書いたYV16->YUY2変換がこっちのものよりも速かったので、同じものに変更しました。

PlanarTools その2

PlanarToolsを更新しました。

PlanarTools
PlanarTools-0.2.0.zip

今回はRGBToRGBというフィルタを追加しました。
RGB24<->RGB32を行う、ConvertToRGBのRGB入力専用版です。
名前はPlanarToolsなのにplanar formatは全く関係ありません…どうしてこうなった?

このフィルタはそもそもavisynth+のSSSE3版ConvertToRGBがなんだか妙に遅いような気がしたので、それを検証するために書いたものです。
なんであれは_mm_alignr_epi8(PALIGNR)を使わないで24バイトずつ処理してるんですかね?

結果としては、こっちのコードのほうが倍近く速いようです。
特に工夫らしいこともしていない、安直なコードなんだけどなぁ…。

2015年9月10日木曜日

PlanarTools

avisynth2.6/avisynth+用プラグインをまた書きました。

PlanarTools
PlanarTools-0.0.1.zip

RGBな素材に対してmasktools2とかのplanar format専用フィルタを使うときの補助用フィルタです。

内蔵フィルタを組み合わせても同じことは出来ますが、いちいち関数化したりするのもめんどいし、また内蔵でもShowAlphaとかMargeRGBとかはほぼ最適化なしな状態で遅いので、自分的には需要があります。

今回RGB24<->YV24をSSSE3なしでSIMD化する方法としてこれを使いました。
これを初めて見たときは目から鱗でしたね。
UtVideoの梅澤さんも「まったく同じ操作5回で完了というのは美しい」と言ってました。

うん、お美事にございまする。

追記:
テンプレート使って実行時分岐を減らしたら少し速くなりましたので0.0.1を上げました。
でもバイナリサイズも倍以上に膨れましたが…。

なお配布しているバイナリは/arch:SSE2でビルドされていますが、/arch:AVXにすればVEX-SSEが使われるのでもう少し速くなります。
興味のある人は自分でビルドしてみてください。

2015年9月1日火曜日

Google Maps API V3の叩き方 その2

さて前回書いたコードだが、実は明らかに無駄な部分がある。
無駄を省けばこうなる。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
</head>
<body>
<div id="gmap" style="width:640px;height:480px;margin: 0 auto;"></div>
<script src="//maps.googleapis.com/maps/api/js?sensor=FALSE"></script>
<script>
(function() {
var map = new google.maps.Map(document.getElementById("gmap"), {
  center: new google.maps.LatLng(33.58922, 130.3928),
  zoom: 12,
  mapTypeId: google.maps.MapTypeId.ROADMAP
});

var info = new google.maps.InfoWindow();

function putMarker(p) {
  var marker = new google.maps.Marker({
    position: new google.maps.LatLng(p.lat, p.lng),
    icon: "//chart.apis.google.com/chart?chst=d_map_pin_icon_withshadow&chld=bus|" + p.color,
    title: p.name,
    map: map
  });
  google.maps.event.addListener(marker, "click", function() {
    info.setContent(
      "<p style='font-size:120%;font-weight:bold;'>" + p.name +"</p>" +
      "<p>" + p.addr + "</p>");
    info.open(map, marker);
  });
}

var place = [
  {
    name: "中央区役所", color: "FF0000",
    lat: 33.5892217, lng: 130.3928651,
    addr: "福岡県福岡市中央区大名2丁目5-31",
  }, {
    name: "博多区役所", color: "00FF00",
    lat: 33.5915037, lng:130.4147805,
    addr: "福岡県福岡市博多区博多駅前2丁目9-3",
  }, {
    name: "東区役所", color: "0000FF",
    lat: 33.617762, lng: 130.417401,
    addr: "福岡県福岡市東区箱崎2丁目54?1",
  }, {
    name: "早良区役所", color: "FFFF00",
    lat: 33.5818585, lng: 130.3484381,
    addr: "福岡県福岡市早良区百道2丁目1",
  }, {
    name: "南区役所", color: "00FFFF",
    lat: 33.561562, lng: 130.426442,
    addr: "福岡県福岡市南区塩原3丁目25-1"
  }, {
    name: "西区役所", color: "FF00FF",
    lat: 33.5828543, lng: 130.3232053,
    addr: "福岡県福岡市西区内浜1丁目1-4-1"
  }
];

for (var i = 0; i < place.length; ++i) {
  putMarker(place[i]);
}
})();
</script>
</body>
</html>
情報ウィンドウを複数同時に表示したくないのであれば、最初からInfoWindowは一つだけnewして、イベントのたびにsetContent->openすればいいだけ。
わざわざ現在表示してるオブジェクトを変数に登録したりcloseしたりする必要はない。
調べてた(サンプルになりそうなものを探してた)時になんか違和感を感じてたんだが、原因はこれだったか…。

Google Maps API v3の叩き方

メモ代わり
一番めんどくさいのはピンを刺す場所をgoogle mapで探して緯度と経度を調べることなのは言うまでもない。
Google Maps JavaScript API V3 Reference
dynamic_icons

ところでマーカーにimage Chartsのdynamic icon使えるのはお手軽でいいのですが、image Chartsってdeprecatedってことは廃止予定なんですよね?
mapsのほうにアイコンだけでも持ってきてほしいものですが…

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
</head>
<body>
<div id="gmap" style="width:640px;height:480px;margin: 0 auto;"></div>
<script src="//maps.googleapis.com/maps/api/js?sensor=FALSE"></script>
<script>
(function() {

function putMarker(p, map, toggleMarker) {
  var info = new google.maps.InfoWindow();
  var marker = new google.maps.Marker({
    position: new google.maps.LatLng(p.lat, p.lng),
    icon: "//chart.apis.google.com/chart?chst=d_map_pin_icon_withshadow&chld=bus|" + p.color,
    title: p.name,
    map: map
  });
  google.maps.event.addListener(marker, "click", function() {
    info.setContent(
      "<p style='font-size:120%;font-weight:bold;'>" + p.name +"</p>" +
      "<p>" + p.addr + "</p>");
    toggleMarker(info, map, marker);
  });
}

var toggleMarker = (function() {
  var current = null;
  return function(info, map, marker) {
    if (current !== null) {
      current.close();
    }
    info.open(map, marker);
    current = info;
  };
})();

var place = [
  {
    name: "中央区役所", color: "FF0000",
    lat: 33.5892217, lng: 130.3928651,
    addr: "福岡県福岡市中央区大名2丁目5-31",
  }, {
    name: "博多区役所", color: "00FF00",
    lat: 33.5915037, lng:130.4147805,
    addr: "福岡県福岡市博多区博多駅前2丁目9-3",
  }, {
    name: "東区役所", color: "0000FF",
    lat: 33.617762, lng: 130.417401,
    addr: "福岡県福岡市東区箱崎2丁目54?1",
  }, {
    name: "早良区役所", color: "FFFF00",
    lat: 33.5818585, lng: 130.3484381,
    addr: "福岡県福岡市早良区百道2丁目1",
  }, {
    name: "南区役所", color: "00FFFF",
    lat: 33.561562, lng: 130.426442,
    addr: "福岡県福岡市南区塩原3丁目25-1"
  }, {
    name: "西区役所", color: "FF00FF",
    lat: 33.5828543, lng: 130.3232053,
    addr: "福岡県福岡市西区内浜1丁目1-4-1"
  }
];

var map = new google.maps.Map(document.getElementById("gmap"), {
  center: new google.maps.LatLng(33.58922, 130.3928),
  zoom: 12,
  mapTypeId: google.maps.MapTypeId.ROADMAP
});

for (var i = 0; i < place.length; ++i) {
  putMarker(place[i], map, toggleMarker);
}
})();
</script>
</body>
</html>


2015年8月29日土曜日

YV12To422 その2

YV12To422を更新しました。

https://github.com/chikuzen/YV12To422

YV12To422-1.0.1.zip

低負荷でそこそこ高速にはなってるので、とりあえずddcc.dllのyv12toyuy2や本体内蔵フィルタのConvertToYUY2の置き換えにはなると思いますが、なにぶん変換のパターンが多い(interlaced(2) x itype(3) x cplace(4) で24パターン + lshift + yuy2)ので確認漏れとかありそうです。

不具合を見つけたら報告おねがいします。


今回cubic補間の実装のため、avisynth+のresamplerのコードを読みましたが、ずいぶんわかりやすくなってますね。
avisynthのインラインASMコードはまったく分からなかったのと比べてすごい違いです。
やってること自体はすごく簡単だったのでちょっとびっくりしました。

追記:
20150831 ちょっと修正したのでバイナリを上げなおしました。