curlを最新版へソースインストール
ruby関連の勉強を始めてみようとしたけど
なんか出る
/tmp/ruby-build.20181006035131.5059 ~/.rbenv/plugins/ruby-build curl: (35) Peer reports incompatible or unsupported protocol version. ~
環境
vangrant上のcentos7(64bit)
なんかcurlが古いらしい
$ curl -V curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.15.4 zlib/1.2.7 libidn/1.28 libssh2/1.4.3 Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz $
証明書関連で動かなくなった感じ?
最新をソースコードよりインストールする
yumでツールをインストール
sudo yum install -y openssl-devel libmetalink-devel libssh2-devel c-ares-devel lbzip2
ダウンロード&インストール
wget https://curl.haxx.se/download/curl-7.61.1.tar.gz tar zxf curl-7.61.1.tar.gz cd curl-7.61.1 ./configure --enable-libcurl-option make sudo make install
インストールパスを間違えたので古いやつを削除してリンクにする
sudo rm -f /usr/bin/curl sudo ln -s /usr/local/bin/curl /usr/bin/curl
確認
$ curl -V curl 7.61.1 (x86_64-pc-linux-gnu) libcurl/7.61.1 OpenSSL/1.0.2k zlib/1.2.7 Release-Date: 2018-09-05 Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL libz UnixSockets HTTPS-proxy $
rbenvでインストールができるようになった\(^o^)/
[vagrant@localhost ~]$ rbenv install 2.3.7 Downloading ruby-2.3.7.tar.bz2... -> https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.7.tar.bz2 Installing ruby-2.3.7... Installed ruby-2.3.7 to /home/vagrant/.rbenv/versions/2.3.7 [vagrant@localhost ~]$
参考
cURLの最新版をインストールする | スターフィールド株式会社
ありがとうございます
go言語の学習:websocketで画像を送信し、webで表示
できたの
なにこれ?
websocketサーバより1秒単位で画像をバイナリ形式で送信したもの
ソース(サーバ側)
package main import ( "log" "net/http" "golang.org/x/net/websocket" "time" "io/ioutil" "image" "gocv.io/x/gocv" "image/color" "bytes" "image/jpeg" "os/user" ) var ( black = color.RGBA{0, 0, 0, 0} ) func main() { name := "server" log.Println(name + " start") http.Handle("/ws", websocket.Handler(WsHandler)) err := http.ListenAndServe(":8001", nil) if err != nil { panic("ListenAndServe: " + err.Error()) } log.Println(name + " end") } func WsHandler(ws *websocket.Conn) { log.Println("connect") // 自動送信 go autoSend(ws) // 受信処理監視 for { var b []byte err := websocket.Message.Receive(ws, &b) if err != nil { log.Println(err) break } } } // 任意の画像を送信する func autoSend(ws *websocket.Conn) { t := time.NewTicker(1 * time.Second) for { select { case <-t.C: // ユーザディレクトリ取得 user, err := user.Current() if err != nil { log.Println(err) return } // 画像ファイル読み込み b, err := ioutil.ReadFile(user.HomeDir + "/Desktop/" + "pug3_pic1.jpg") if err != nil { break } // 画像変換 atom, err := gocv.IMDecode(b, gocv.IMReadUnchanged) if err != nil { log.Println(err) return } defer atom.Close() // 日時取得 now := time.Now() // 偶数 if int(now.Second()) % 2 == 0 { gocv.Rectangle(&atom, image.Rect(400, 400, 900, 700), black, 2) } else { gocv.Rectangle(&atom, image.Rect(400, 400, 900, 700), black, -1) } // 文字列を出力 timeStr := now.Format("2006/01/02 15:04:05") gocv.PutText(&atom, timeStr, image.Pt(20, atom.Rows() - 40), gocv.FontHersheyComplex, 1, black, 1) // 画像に変換 image, err := atom.ToImage() if err != nil { log.Println(err) return } var jpegBytes []byte buf := bytes.NewBuffer(jpegBytes) if err := jpeg.Encode(buf, image, nil); err != nil { log.Println(err) } b = buf.Bytes() websocket.Message.Send(ws, b) log.Println("send") } } }
ソース(クライアント側)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <img id="img1" src=""> <script> var uri = "ws://localhost:8001" + "/ws"; webSocket = new WebSocket(uri); webSocket.binaryType = 'blob'; webSocket.onopen = function(e) { console.log("open"); }; webSocket.onmessage = function(e) { console.log("message"); var data = e.data; if (data.constructor === Blob) { document.getElementById('img1').src = URL.createObjectURL(data); } }; webSocket.onclose = function(e) { console.log("close"); }; </script> </body> </html>
ソース(クライアント版2)
package main import ( "log" "golang.org/x/net/websocket" "strconv" ) var ( doneCh chan bool origin = "http://localhost:8001/" url = "ws://localhost:8001/ws" ) func main() { name := "client" log.Println(name + " start") doneCh = make(chan bool) ws, err := websocket.Dial(url, "", origin) if err != nil { log.Fatal(err) return } go receiveMsg(ws) <-doneCh log.Println(name + " end") } // 受信 func receiveMsg(ws *websocket.Conn) { var b []byte for { err := websocket.Message.Receive(ws, &b) if err != nil { log.Println(err) doneCh <- true break } log.Printf("Receive datasize=" + strconv.Itoa(len(b))) } }
所感
いろいろ悩んだけど基本は画像をバイナリで送信するだけだった感じ
動画のストリーミングという感じではないのでそこまで難しくないかも…
最初はwebsocketの送受信がうまく行かなかったけどw
go言語の学習:画像を読み込み、文字を追加
日本語ができない
時間は気にしないでwww
前のソースを一部回収
package main import ( "gocv.io/x/gocv" "log" "os/user" "time" "io/ioutil" "image/color" "image" ) var ( // サイズ w = 640 h = 480 // 色定義 black = color.RGBA{0, 0, 0, 0} blue = color.RGBA{0, 0, 255, 0} red = color.RGBA{255, 0, 0, 0} white = color.RGBA{255, 255, 255, 0} yellow = color.RGBA{255, 255, 0, 0} color2 = color.RGBA{128,128,128,0} ) func main() { // ユーザディレクトリ取得して保存先を作成 user, err := user.Current() if err != nil { log.Println(err) return } // img読み込み img_file_path := user.HomeDir + "/Desktop/" + "pug3_pic1.jpg" // file b, err := ioutil.ReadFile(img_file_path) if err != nil { log.Println(err) return } // 画像取得 atom, err := gocv.IMDecode(b, gocv.IMReadUnchanged) if err != nil { log.Println(err) return } defer atom.Close() // sample1描画 sample1(&atom) // 領域作成 img2 := gocv.NewMatWithSize(atom.Rows(), atom.Cols(), atom.Type()) // 短径(線) gocv.Rectangle(&img2, image.Rect(400, 20, 900, 400), blue, 3) // 短径(塗りつぶし) gocv.Rectangle(&img2, image.Rect(400, 20, 900, 400), color2, -1) // 重ねる gocv.AddWeighted(atom, 1, img2, 0.5, 0, &atom) // 文字列を出力 timeStr := time.Now().Format("2006/01/02 15:04:05") gocv.PutText(&atom, timeStr, image.Pt(20, atom.Rows() - 40), gocv.FontHersheyComplex, 1, black, 1) // 出力画像パス file_path := user.HomeDir + "/Desktop/" + time.Now().Format("20060102150405") + ".jpg" // 保存 gocv.IMWrite(file_path, atom) } func sample1 (img *gocv.Mat) { // 短径描画 gocv.Rectangle(img,image.Rect(10, 10, 100, 100), black, 5) gocv.Rectangle(img,image.Rect(200, 15, 300, 350), blue, 5) gocv.Rectangle(img,image.Rect(10, 400, 600, 470), yellow, -1) // -1の場合は塗りつぶし gocv.Rectangle(img,image.Rect(40, 350, 550, 450), red, -1) // -1の場合は塗りつぶし // 多角形描画 ps := make([][]image.Point, 1) p := make([]image.Point, 4) p[0] = image.Pt(int(0.1*float64(w)), int(0.1*float64(h))) p[1] = image.Pt(int(0.1*float64(w)), int(0.4*float64(h))) p[2] = image.Pt(int(0.3*float64(w)), int(0.2*float64(h))) p[3] = image.Pt(int(0.3*float64(w)), int(0.1*float64(h))) ps[0] = p gocv.DrawContours(img, ps, 0, red, -1) // -1の場合は塗りつぶし }
使うようになったもの
gocv.IMDecode
→ バイナリを読み込んで変換してくれる
gocv.AddWeighted
→ 既存の短径領域に別の短径領域を重ねる
gocv.PutText
→ 指定の場所にテキストを追加
所感
IDEってやっぱり良いです\(^o^)/
viなどでもなんかできそうですけど、commandキーや入力している間に引数やメソッドの候補がでるのは嬉しい
go言語の学習:gocvで画像を作成して出力
gocv
Home :: GoCV - Golang Computer Vision Using OpenCV 3
opencvでなんかいろいろやってくれるライブラリ
インストールするまでくっそ面倒
macの場合はbrew installで簡単そうですけど
なんかいろいろエラーでて大変でした
・pythonいれたり、クリーンアップしたり、brew docterして問題解決したり色々やったなあ…
・多分、最新バージョンならwindowsでもできると思います
ソース
package main import ( "image" "image/color" "gocv.io/x/gocv" "log" "os/user" "time" "os" "image/jpeg" ) var w = 640 var h = 480 func main() { // 描画領域作成 atom := gocv.NewMatWithSize(h, w, gocv.MatTypeCV8UC3) defer atom.Close() // 色定義 black := color.RGBA{0, 0, 0, 0} blue := color.RGBA{0, 0, 255, 0} red := color.RGBA{255, 0, 0, 0} white := color.RGBA{255, 255, 255, 0} yellow := color.RGBA{255, 255, 0, 0} // 短径描画 gocv.Rectangle(&atom,image.Rect(0, 0, 640, 480), white, -1) gocv.Rectangle(&atom,image.Rect(10, 10, 100, 100), black, 5) gocv.Rectangle(&atom,image.Rect(200, 15, 300, 350), blue, 5) gocv.Rectangle(&atom,image.Rect(10, 400, 600, 470), yellow, -1) // -1の場合は塗りつぶし gocv.Rectangle(&atom,image.Rect(40, 350, 550, 450), red, -1) // -1の場合は塗りつぶし // 多角形描画 ps := make([][]image.Point, 1) p := make([]image.Point, 4) p[0] = image.Pt(int(0.1*float64(w)), int(0.1*float64(h))) p[1] = image.Pt(int(0.1*float64(w)), int(0.4*float64(h))) p[2] = image.Pt(int(0.3*float64(w)), int(0.2*float64(h))) p[3] = image.Pt(int(0.3*float64(w)), int(0.1*float64(h))) ps[0] = p gocv.DrawContours(&atom, ps, 0, red, -1) // -1の場合は塗りつぶし // ユーザディレクトリ取得して保存先を作成 user, err := user.Current() if err != nil { log.Println(err) return } file_path := user.HomeDir + "/Desktop/" + time.Now().Format("20060102150405") + ".jpg" // 保存 //gocv.IMWrite(file_path, atom) // 画像に変換 image, err := atom.ToImage() if err != nil { log.Println(err) return } // file出力 file, errOs := os.Create(file_path) if errOs != nil { log.Println(err) return } defer file.Close() // jpeg形式で出力 if err := jpeg.Encode(file, image, &jpeg.Options{100}); err != nil { log.Println(err) return } /* // bytes変換 var jpegBytes []byte buf := bytes.NewBuffer(jpegBytes) if err := jpeg.Encode(buf, image, nil); err != nil { log.Println(err) } jpegBytes = buf.Bytes() */ }
できたもの(適当)
所感
複雑な画像編集することが容易にできるような感じとのこと
文字入れたり、グレースケールとかできたらやってみたい
go言語の学習:構造体よりタグ情報を取得
構造体にあるjsonなどのタグより取得
package main import ( "fmt" "reflect" ) type Sample struct { no int `sampletag:"aaaaa"` name string `sampletag:"bbbbb"` age int `sampletag:"ccccc"` } func main() { fmt.Println("start") // Sample1インターフェースを定義 var sample1 Sample // 型の取得 t := reflect.TypeOf(sample1) // タグの情報を取得 for i:=0;i<t.NumField();i++ { item := t.Field(i) fmt.Printf("index: %2d, name:%10s, type:%10s, tag:%10s\n", i, item.Name, item.Type.Name(), item.Tag.Get("sampletag")) } fmt.Println("end") }
↓
start index: 0, name: no, type: int, tag: aaaaa index: 1, name: name, type: string, tag: bbbbb index: 2, name: age, type: int, tag: ccccc end
DBのORMやjsonのエンコード、デコードなどで使用されている
タグ情報を設定することで構造体の項目のバリデーションなどにも併用できる感じ…
go言語の学習:ポリモーフィズムのパターン
Javaとかではクラスにinterfaceとか定義して使用する
goの場合は構造体自体はメソッドを実装するが、定義されているインターフェースは定義しない
サンプル
package main import ( "fmt" ) // Sample1インターフェース、メソッドを定義 type Sample1 interface { Print() } // Hoge構造体、Printメソッドを用意 type Hoge struct { a int } func (c Hoge) Print() { fmt.Println("hoeghoge") fmt.Println(c.a) } // Foo構造体、Printメソッドを用意 type Foo struct { a int } func (c Foo) Print() { fmt.Println("foofoo") fmt.Println(c.a) } func main() { fmt.Println("start") // Sample1インターフェースを定義 var sample1 Sample1 // 構造体を生成 hoge := Hoge{a: 100} foo := Foo{a: 500} // sample1変数にHoge構造体を設定して実行 sample1 = hoge sample1.Print() // sample1変数に Foo構造体を設定して実行 sample1 = foo sample1.Print() fmt.Println("end") }
interface型に共通の呼び出したいメソッドを定義しておくことで実行することが可能
しかし、この場合はSample1を定義しておかないといけない
var sample1 interface{}
のように定義していないinterfaceを使用した場合は動かすことができるか?
↓
typeで定義されたメソッドを使用前に定義することで
対応は可能、しかし、設定された変数には定義されていないこともあるため、型アサーションで存在チェックすることが必要
// Sample1インターフェース、メソッドを定義 type Sample1 interface { Print() } // sample1変数にHoge構造体を設定して実行 sample1 = hoge a, ok := sample1.(Sample1) if !ok { fmt.Println("Print実行不可") return } a.Print()
所感
まああれかな、JavaでObject型で受け取ってどのクラス情報を保持するかみたいな感じと思います。
今回でいうとinterface型で定義して受け取って入れば対象のinterfaceのメソッドに応じて処理を切り替えられる感じ
interface型の仕組みを上手く理解していないのでこのあたり考えて対応する必要がありそうです。
go言語の学習:interface型の値設定について
interface型は基本的にはどんな値も設定できる
package main import ( "fmt" ) func main() { fmt.Println("start") var a interface{} a = int(10) a = int64(10) a = string(65) fmt.Printf("%+v\n", a) fmt.Println("end") }
設定はできる…
しかし、そのままでは文字列連結や加算、減算などはできないようになっている感じ
型変換
package main import ( "fmt" ) func main() { fmt.Println("start") var a interface{} a = int(10) a = a.(int) * 100 fmt.Printf("%+v\n", a) fmt.Println("end") }
「変数.(設定されている値のデータ型)」でその値へ変換してくれます
リフレクションでinterfaceに設定されたデータ型を確認できる
package main import ( "fmt" "reflect" ) func main() { fmt.Println("start") var a interface{} var v reflect.Value a = int(10) v = reflect.ValueOf(a) fmt.Printf("a(type): %+v\n", v.Type()) a = int64(100) v = reflect.ValueOf(a) fmt.Printf("a(type): %+v\n", v.Type()) a = "aaaaaaaaaa" v = reflect.ValueOf(a) fmt.Printf("a(type): %+v\n", v.Type()) fmt.Printf("%+v\n", a) fmt.Println("end") }
↓
start a(type): int a(type): int64 a(type): string aaaaaaaaaa end
まとめ
構造体とか定義せずにいい感じのデータ型が混ざったやつって定義したいなぁぁぁぁ