Engineerになりました。備忘録も兼ねて技術ネタを適当に。技術以外はこっち→http://mitsu9.hatenablog.com/この広告は、90日以上更新していないブログに表示しています。-HTTP、URI、HTML、そしてREST-」を読んだ(/・ω・)/これまでWebサービスを使ったり、実装したりとしてきたけど、改めて体系的にWebについて勉強するといろいろ良かった。就職前に読んでおいて良かったなーと思った。Webサービス作り始めの頃とかに読んでおきたかった。各章で書いてあったことと感じたことをメモしておく。Webとは何かさまざまなWebWebサイトユーザーインターフェースとしてのWeb(ルータの設定画面など)プログラム用APIとしてのWebWebっていろんなところで使われてるねって話。Webの歴史Web以前のインターネット・ハイパーメディアの紹介・問題点Webの登場と標準化の歴史Web以前のインターネットとか知らないことが多くておもしろかった。アーキテクチャスタイルクライアント/サーバステートレスサーバキャッシュ統一インターフェース階層化システムコードオンデマンドWeb世界の秩序を守るためにもRESTfulなサービスやAPIを作ろう。IdentifierURIスキームユーザ情報ホスト名ポート番号パスクエリパラメータURIフラグメント絶対URIと相対URI相対URIを使うときはベースURIが必要ベースURIはHTMLので指定できるURIで使用できない文字を使うときはUTF-8で%エンコーディングする相対URIとかは気にしたことなかったので勉強になった。変わらないURIURIが変わるときはリダイレクトするURIの重要性URIはリソースの名前URIは寿命が長いURIはブラウザがアドレス欄に表示するリンク先に飛んだら404とか悲しい気持ちになるし、Web的にも良くないよね。良いURIをつけられるようになろう。1.1が今広く使われているリクエストメッセージリクエストラインヘッダボディレスポンスメッセージステータスラインヘッダボディステートレス利点:サーバはアプリケーション状態を覚える必要がない→シンプル、スケーラブル欠点:パフォーマンスの低下、通信エラーへの対処HTTPは凄いシンプルなプロトコル。ここまで広く使われているんだろうなーと思った。一方でシンプルだからこその欠点もあるのでそれは知っておく必要があるしいい勉強になった。操作対象のリソースの状態を変化させないべき等と安全は意識しないと、使い勝手の悪いサービスを作ってしまうなーと感じた。ステータスコードステータスコードの重要性クライアントの挙動を決める間違ったステータスコードはクライアントを混乱させるステータスコードは自作できるクライアントが未知のステータスコードを受け取った場合は、先頭数字を見て最低限の処理をおこなう良くみるステータスコードは勝手に覚えてるけど、それ以外のものはいつかゆっくり見てみたい。認証キャッシュ持続的接続HTTPがシンプルに設計され、かつ広く使われているのはこのヘッダが大きな役割をしてるなと感じた。上手く使いこなせるようにまずはどんなヘッダがあるかを知らないとなーと。複数のXMLフォーマットを組み合わせる時に名前の衝突を防ぐHTMLの本当の基本しか書かれていなかったので知ってることが多かった。XMLの名前空間の話とかは見たことあったけどよくわかってなかったので勉強になった。意味論リソースが持つ意味を確定させる人間が読んで解釈するだけでなくプログラムも解釈できるようにする標準化済みのmicroformats(一部)hCalendar:イベント情報hCard:プロフィール情報rel-lisence:ライセンス情報イベントとかよく使うものは標準化しておくとスクレイピングなどするときに統一感があって楽になるって感じなのかな。標準化されててもそれを使うか独自実装するかは個々人の勝手やけど、標準化されたものに従えばWeb世界は整理された綺麗なところになる。ここらへんは知ってるか知らないかで大きく変わるからいろいろ知っておきたい。RSSの標準仕様策定AtomはRSS(ブログ)だけでなく検索エンジンや写真管理など様々使えるAtomのリソースモデルメンバリソースエントリリソースメタデータ:ID、タイトル、著者、更新日時が必須。他には概要説明やカテゴリなど。ArchivingOpenSearchRSSとかでAtomって文字は見たことあったけど、今回初めてきちんと勉強した。拡張もいろいろされていて、広く使われているんだろうなーという印象。便利やとは思うけどどういう時に適しているかまではわからなかったので、一回自分で書くなりして触ってみたいなと感じた。ProtocolAtomを利用したリソース編集プロトコルの規定AtomのエントリーをGETとかPOSTとかできるよーぐらいの理解しかしてない。ブログサービスとかはこういう風にして設計・実装されてるのかなーとか思った。ブーリアン、nullJSONPによるクロスドメイン通信JSONはAPI叩く時に良く見てたし便利だよねって感じ。読み取り専用のWebサービスの設計リソース設計リソース指向アーキテクチャWebサービスで提供するデータの特定データをリソースに分けるリソースにURIで名前をつけるクライアントに提供するリソースの表現を設計するリンクとフォームを利用してリソース同士を結びつけるイベントの標準的なコースを検討するエラーについて検討する郵便番号検索サービスの例をあげて説明されてたのでイメージしやすくわかりやすかった。設計に関しては場数踏むしかないのかなとは思ってるので、本に書かれていたことを意識しながらいろいろ作っていきたいなと思った。ロック楽観的ロックバッチ処理、トランザクション、排他制御まで考えて実装したことがなかったので、大規模なサービスとかエラーが許されないサービスとかだといろいろ考えないといけないんだなと感じた。これらを実現するために特別なプロトコルなどは利用しておらずHTTPのみで実現されているのは凄いなと思った。ここらへんはある程度手法が確立されていてデザインパターンみたいになっているのかなと思うので、そこらへんも勉強していかなきゃなーと感じた。APIを分けて考えない設計手法は様々知っていると適切なカードが切れて将来便利かもしれないと思った。友達と遊ぶようにマイクラ鯖たてました。言ってもそんなことのできるデスクトップPCは持ってないのでAWS使いました。公開するなら荒らし対策などやることはいろいろあるけど、今回は友達で遊べる最低限の設定まで。IPの設定マイクラサーバーの設定とりあえず必要なもののインストール。java入ってるか確認。必要なら変更などする。git今回はspigotを使ってサーバー環境を整えていきます。詳細まではわかってないけど、調べたところ公式よりもspigotが良いらしい。起動/停止スクリプトの作成いちいちコマンド打つのもあれなのでスクリプト作ります。spi_stop.shちゃんと動くか確認しておく監視ツールの導入などmackerelエージェントのインストールサーバたてたらとりあえずmackerel入れとけ派の人なので入れます。自分は何かあったらslackに飛ばすように設定してるので鯖落ちとかはすぐ気付けるようにしてます。sh定期的に再起動するように設定ずっと起動しっぱなしは良くないので定期的に再起動するように設定します。Judgeに書いてある通りです、ってのも素っ気ないので以下にスクショ貼ります。図のような状況において、水たまりそれぞれの面積と全体の面積を出すという問題です。入力として\、_、/の列を受け取り、出力は全総面積、水たまりの数、各水たまりの面積になります。上の図に対応する入力、出力は以下のようになります。9となっていることを示しています。State-of-the-Arsのコードを参考にしながら考えていきました。入力が\のときはそのインデックスをスタックに保存する入力が/の時はスタックからpopし、現在のインデックスと組み合わせて横向きに面積を計算する計算した面積の総和をとって総面積を計算するといった感じです。これだけでは各水たまりの面積を計算できないので、/の時にpopしたインデックスと計算した面積のタプルを保存する必要に応じて上記のタプルを結合していく(水たまりを結合する操作に相当)ということもします。以上のために2つのスタックを用意します。\のインデックスを保存するスタックpopしたインデックスと計算した面積のタプルを保存するスタックこれだけだと意味不明なので例を出しながら説明します。19となっている箇所を用いて説明します。ちなみに入力は\/\\\\/_/\\///となります。今後はこの入力をインデックスと合わせて説明するので、簡単な表を書いておきます。0\なのでスタック1にインデックスを保存します。1/なのでスタック1からpopします。popしたインデックスとこの計算結果をスタック2に保存します。5\らをスタック1に積んでいきます。6/なのでスタック1からpopします。popしたindexの5は、スタック2に保存したタプルに入っているindexである0より大きいので、そのままスタック2に保存します。1)スタック2が水たまりの様子を表しているので、これは面積1の水たまりが2つあることを示しています。実際にここまで読み込んだ時の様子は以下のようになっています。7のとき_なので特に何もしません。8のとき/なので、スタック1からpopします。popしたindexである4はスタック2に積まれているタプルに保存されたindexである5より小さいので、水たまりは結合されます。5を合わせて保存します。この時のスタックの状態は以下のようになります。1)この時の状態はこんな感じ。13/なのでスタック1から3をpopする。4)はindexの値が大きいのでこれらを結合する。1)図的にはこんな感じ。結果スタックの状態は以下のとおり。したがって、スタック2を見ると、面積1の水たまりと、面積19の水たまりがあることがわかる。1)コードrubyで書きました。最適化できそうやけどとりあえずはこれで解けます。0の時にmapがうまくいかない??endgithubにもあげてます。github.com最後に今回は最初さっぱりわからず30分くらい問題とにらめっこしてたのですが、横向きに面積を計算する、その時面積はインデックスの引き算で求めることができる、ということに気づくと後はすぐに解けました。見方を変えれば簡単に解けるけど、その見方に気付けないという典型的な問題でした。いう見方は普段から引き出しを増やすしかないのかなーと思うので今後も勉強を続けていきたいなーと思いました。opencv画像処理の授業取っててruby+opencvで実装したのでその時のことをメモメモφ(・・opencvといえばc++かpythonってイメージがあるけど、最近勉強中のrubyで実装したいなーと思ったのでしてみた。開発環境rubyでopencvを使うためのgemがopencv3系に対応していないのでこんな感じ。2.4.13ruby-opencvインストール関係で叩いたコマンドは以下の通り。地味にハマったのはopencv3も入っているからオプションでopencv2の方を見るようにしないといけなかったってところ。--with-opencv-dir=/usr/local/Cellar/opencv/2.4.13.22値化とは画像を白(1)か黒(0)の2つの値のみにすること。色の情報が必要では無く形に着目するときとかに使うと良い。情報量を減らせるので計算の面でもシンプル&高速になるとかなんとか。現実世界やと、駐車場でナンバープレート見て清算済みなら勝手に開けてくれるとかあるけど、ああいうときに使われているらしい。(雑な理解やけど多分だいたいあってる)2値化の仕方さて、どうやって2値化するかって話やけど、中身はすごい簡単。各ピクセルの濃度値が閾値より大きければ黒、小さければ白にするだけ。自分で実装してもそんなに大変ではないけど、opencvには閾値を渡せば2値化してくれるメソッドがあるので凄い簡単。2値化するところは以下の通り。カラーの画像をグレースケールにしてから、threshold()を呼べば終わり。引数については詳しく調べてなくて、255は8bitカラーの最大値からきててとりあえずこう書いとけばいいという雑な理解。:binary)end2値化は簡単にできるけど、問題になるのはその閾値をどうやって決めるかという話になって、それはいくつかアルゴリズムがあるらしい。今回はこの中で微分ヒストグラム法と判別分析法を実装した。微分という名前の通り、濃度値の変化が大きいところに着目して閾値を決める方法。ヒストグラム法やからヒストグラムを作るんやけど、どういうものかというと横軸が濃度値、縦軸が微分値の和になるようなヒストグラム。普通は縦軸が単に画素数になるから、ここでは微分値を重みとしてちょっと変化させてるという感じ。|を周辺8マス分計算してその総和を取る。ヒストグラムを作るところは以下のように実装した。histend全てのピクセルを網羅するためにx座標とy座標の直積を取る必要があって、それは[*0...gray_img.rows].product([*0...gray_img.cols]).eachと書いた。product()を使うと直積を取ってくれるのだが、配列で渡す必要があるので[*0...gray_img.rows]としてrangeではなく配列にした。個人的にはこの行がなんかもうちょっといい感じに書けないのかなーと思ってるけど、書き方がわからないのでこのまま。x)の返り値はCvScalar型になってて、カラーだとRGB値、グレースケールだと輝度値が入っている。CvScalarは4つのdoubleを持つ配列になっているので、b[0]のような書き方になる。ちなみに、カラーのときはBGRの順に値を持っているので注意が必要。rangeでエラー吐きまくってた。微分値を計算するところは、周辺8マスを計算するためにまた直積を書いて実装している。この書き方やと縦横3×3の9マスを網羅してて基準になるマスも入るけど、計算結果は変わらないので9マス分計算している。あとは、端っこのピクセルやと隣がいない場合があるのでそのためのチェックもしてる。別名大津の2値化ともいうらしい。ある値を閾値にしたときの分離度なる値を算出してそれが最大になるような閾値を採用するというアルゴリズム。分離度は、閾値を元にそれより暗い/明るいの2つのグループに分けて、それぞれのグループでの分散を求めて、クラス内分散やクラス間分散を定義して、って感じで定義される。この分離度だが、今回はその最大値を求めるという点で大小関係の比較ができれば良いので、結局各グループ内の画素数と濃度値の平均があれば十分になる。数式の詳しい説明はちょっと長くなるのでこちら。実装としては、閾値をある値にした時の分離度を求めて、それが最大になる閾値を返すというメソッドを作るだけなので簡単で、以下の通り。best_tendcreate_histogram()は横軸が濃度値、縦軸が画素数のシンプルなヒストグラムを返すように実装したメソッド。indexが濃度値、値が画素数の配列の形でデータを保持している。画素数は単に配列の値を足していけば良いだけなのでreduce(:+)するだけ。idx}のようにしてまず画素数×濃度値を計算した。そのあとは同じくreduce(:+)で総和を求めて、画素数wで割って終わり。この書き方をすると他のエラーを握りつぶしてしまうのでもしかしたらよくないかも。あと工夫しているところは閾値より大きいところを見るときにhist[t+1..255].map.with_index(t+1)という書き方をしているところ。lenna使ってみました。lennaだと2つの手法の差があまり出なくて向き不向きみたいなのが見えなくて残念やけど。微分ヒストグラム法を使って2値化した画像(閾値=129)判別分析法を使って2値化した画像(閾値=122)最後に一応プログラムはgithubにあげてます。今後も授業でいろいろ実装していく予定なので適宜まとめていこうかなと思ってます。22:05ruby+opencvで画像処理(2値化)Tweet広告を非表示にするもっと読むコメントを書く2017-02-282017年2月の振り返り2月も終わりなので今月の振り返り。就活に時間割いたので基本的に何もしてない。M1の進捗とM2の予定をプレゼンしなきゃいけなかったのでそれの作成と発表しかしてないですね。js前半はVPS上でdockerいろいろ触ってました。インフラエンジニアで就活してたのでさすがに知らなさすぎてやばいなと思って勉強してたって感じ。その流れでgoに入門したりもしてました。後半はruby、railsの勉強をしてました。これはインターン先がrailsだったから勉強してました。js周りの勉強もその流れでしてました。基本的には就活に向けてってのが多かったけど、インフラからフロントまで一通り触った1ヶ月だったなーという感想。今年に入って広く浅くやってる感じになってるから、そろそろどれかに決めて深く勉強したいなーと思ってます。techlog前半はしっかりインプットもアウトプットもできたけど、後半はひたすらインプットしてました。アウトプットの意識忘れないようにしていかないと。今月は選考が進んでて面接があったりインターンがあったりという感じ。その中で人に会う度にそういう考え方もあるのかーと思ってました。そのおかげで自分の強みや弱み、どういうことに興味があるのか、何をしたいのかとかを深掘りできたから良かったと思う。院生の就活って推薦使ったり一般でも受ける企業が少なかったりするけど、自分が将来何をしたいのかが不明確なのであれば足を動かしていろんな人に会うと良いと感じました。適当に選んで数年で転職とかはもったいないと思うし、楽しく仕事するためにしっかりこの機会に頭使わないとと思いました。まとめ就活、インターンでいろんなエンジニアの人に会った一ヶ月でした。インターンは大変やったけど楽しい一週間やった。面接や説明会と違ってランチやといろいろ聞けるのでインターンは良い体験でした。技術的には様々学んだけど実際に何か作ったりしていないのでちゃんと身についてない感がある。インターンも終わって自分で好きなものを勉強できる期間に入るので、来月は手も動かしながら深く学んでいきたいと思います。Go読むと良いっぽかったので読みました。途中途中に練習問題があって、それを解きながら進めると適度に手も動かせて良かったです。以下は自分用のまとめです。最後に練習問題の解答をまとめて載せています。("fmt""math")大文字から始めると他から参照可能。小文字からだと外からはアクセスできない。型が同じ時はまとめてok。返り値は複数でもok。x}返り値にあらかじめ名前をつけておくこともできる。その場合returnだけでよし。初期値を与えないときはゼロ値が入る。値"で宣言と初期化をまとめてできる。3型変換は"型名(値)"で可能。constキーワードを用いると定数を宣言可能。定数の時は":="でなく"="。deferFor文は括弧無しversion。something}If文も括弧無しverison。something}特殊なのは簡単な式をIf文の中で書ける。スコープはIf文内のみ。v}Switch文はcaseで強制break。続けるときは"fallthrough"をcaseの最後に書く。Deferを使うと呼び出し元の関数がreturnする時まで評価を遅らせる。(引数は評価されるがその関数は評価されない)複数deferがあるときはLIFOの順で処理される。maps.ポインタが使える。&でポインタを取得、*でポインタが示す先の値を取得。struct"の形で宣言。構造体へはドットでアクセス。4fmt.Println(v.X)}ポインタを用いて構造体へアクセスもできる。このとき(*p).Xと書かなくても勝手に解釈してくれる。[サイズ]型"で宣言。配列の長さは後から変えれない。[10]int配列を便利に扱うためにsliceがある。7]sliceは元の配列の部分を参照しているだけ。したがって、sliceの値を変えると元の配列の値も変わる。sliceを重ねて新たなsliceを作ることができる。[5]sliceはlengthをcapacityを持っている。lengthはsliceに含まれる要素数。capacityはsliceの最初の要素から数えて元の配列の最後の要素までの数。lengthとcapacityはlen(s)とcap(s)の形で取得可能。make関数を用いてsliceを作成。make関数はarrayを作成しそのsliceを返す。cap(b)=5append関数を用いてsliceに要素を追加することができる。capacityを超えたとき、より大きなサイズの配列を割り当て直す。1)rangeを使えば反復処理ができる。rangeを使うと2つの値が返され、1つ目がindex、2つ目がその要素の値。使わない時は"_"で捨てることができる。value)}Mapを用いてキーと値を関連づけることができる。make関数を用いてmapを作成することで要素の追加などが可能。m[key]"の形でキーに対する要素が存在するかを確認できる。ok)無名関数を渡すことも可能。interfacesGoにクラスはないが、レシーバ引数を用いてっぽいことができる。レシーバ引数を使うとドットを用いてアクセス可能。レシーバを伴うメソッドは同じパッケージ内でする必要がある。4}fmt.Println(v.Abs())}ポインタレシーバを用いて関数を宣言することも可能。レシーバの値を更新する時はこちらで。f}ポインタレシーバの時は値でもポインタでもどちらを渡してもうまくやってくれる。OKインターフェースの宣言もできる。明示的に書かなくても実装すればok。{fmt.Println("<nil>")return}fmt.Println(t.S)}nilインターフェースの値は値も具体的な型ももたない。メソッドを呼び出すとランタイムエラーになる。ランタイムエラー}型アサーションができる。i.(T)"の形で、iがTを保持してればtにその値が入り、okにtrueが入る。t=ゼロ値でok=false。ok)型アサーションを使って型Switchができる。v)}Goではエラーをerror変数を用いて表す。エラー型は以下のインターフェース。string}Concurrencygoroutineという並列化機構がある。z)"と書けば別スレッドで動かせる。チャネル型を用いて値のやりとりができる。2つ目の引数でバッファのサイズを指定これ以上値を送信しないことを示すためにチャネルのcloseができる。受信側は2つ目の引数でcloseされているかを知ることができる。チャネルが閉じていればok=falseselectを用いて複数のチャネルを待つことができる。defaultを用いれば待ち状態にはならずdefaultを実行する。time.Millisecond)}syncパッケージを用いて排他制御などをおこなうことができる。手持ちのさくらVPS上で環境作ります。Docker)を参考に導入しました。随時更新されていると思うので最新の情報を参照した方が良いと思います。hello-world表示を見た感じちゃんと動いていれば大丈夫だと思います。linux/amd64というわけで1.13.0が入ったみたいです。ちなみにインストールする際にバージョンを指定することも可能です。インストール可能なバージョンは以下のコマンドで確認できます。docker-engineユーザグループの作成sudo無しで実行できるようにdockerグループを作成します。僕の場合グループは既に存在していたので、ユーザを追加するだけでした。$USER1回ログインし直して設定を適用します。sudo無しで実行できればokです。公式のイメージがあるのでそれを使います。jenkinsコンテナの状態を確認します。pensive_brahmaguptaブラウザからjenkinsをひらきます。runコマンドの実行時にパスワードが表示されているのでそちらを入力します。その後pluginはオススメを選び、ユーザの作成など順序通りに進みます。psコマンドを用いてidを取得します。startコマンドで停止、起動をおこないます。rmコマンドでできます。pensive_brahmaguptaさいごにdockerとjenkinsの環境構築ができました。次回はjenkinsの設定をしてテストの自動化などをしていきたいと思います。07:10docker、jenkinsの導入Tweet広告を非表示にするもっと読むコメントを書く次のページプロフィールid:mtdtx9通信ネットワークの研究してる大学院生です。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。