m_shige1979のときどきITブログ

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

FaceApiを試す。(ローカルよりファイルをアップロードして結果を取得)

基本的にはURLを指定するサンプルしかない

ので探していろいろやってみた。

実装

sample2.go
package main

import (
    "log"
    "net/http"
    "bytes"
    "io/ioutil"
)

func main() {
    key1 := "生成したキー"
    jpegData, _ := ioutil.ReadFile("face.jpg")

    // EndPoint
    endPoint := "https://eastasia.api.cognitive.microsoft.com/face/v1.0"

    // params
    paramStr := "/detect?returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,gender,glasses"

    // URL
    url := endPoint + paramStr
    log.Println(url)

    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jpegData))
    if err != nil {
        log.Fatal("Request:", err)
        return
    }

    req.Header.Set("Content-Type", "application/octet-stream")
    req.Header.Set("Ocp-Apim-Subscription-Key", key1)

    httpClient := &http.Client{}

    resp, err := httpClient.Do(req)
    if err != nil {
        log.Fatal("Do: ", err)
        return
    }

    defer resp.Body.Close()

    byteArray, _ := ioutil.ReadAll(resp.Body)
    log.Println(string(byteArray))

}

2017/11/05 23:02:03 https://eastasia.api.cognitive.microsoft.com/face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,gender,glasses
2017/11/05 23:02:04 [{"faceId":"b28efd98-47db-460f-8556-d1882565d4a9","faceRectangle":{"top":156,"left":173,"width":178,"height":178},"faceAttributes":{"gender":"male","age":33.8,"glasses":"NoGlasses"}}]

必要なこと

application/octet-streamを送信

image/jpegなどではエラーが帰ってきた

所感

クライアントからファイルを送信するサンプルがなかなか見つからない感じ
ファイルの送信する方法はまだ調べないといけない感じ…

AzureのFaceAPIをgo言語で試す

FaceAPIとは?

Face API - 顔認識 | Microsoft Azure
画像より顔を認識してその情報を返すAPI

準備

AzureでFaceAPIのサービスを開始してキーを取得刷る必要があります。

手順

その他サービスより検索

f:id:m_shige1979:20171105214729p:plain

Cognitiveサービスを開始する

f:id:m_shige1979:20171105214739p:plain

FaceAPIを検索して開始する

f:id:m_shige1979:20171105214748p:plain

作成に同意

f:id:m_shige1979:20171105214800p:plain

設定情報を入力して作成

f:id:m_shige1979:20171105214810p:plain

ダッシュボードに追加されたことを確認

f:id:m_shige1979:20171105214822p:plain

エンドポイントを確認

f:id:m_shige1979:20171105214834p:plain

キーを確認

f:id:m_shige1979:20171105214842p:plain

実装

sample1.go
package main

import (
    "log"
    "net/http"
    "bytes"
    "io/ioutil"
)

func main() {
    key1 := "アクセスキー"
    jsonStr := []byte(`{"url":"画像のURL"}`)

    // EndPoint
    endPoint := "https://eastasia.api.cognitive.microsoft.com/face/v1.0"

    // params
    paramStr := "/detect?returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,gender,glasses"

    // URL
    url := endPoint + paramStr
    log.Println(url)

    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
    if err != nil {
        log.Fatal("Request:", err)
        return
    }

    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Ocp-Apim-Subscription-Key", key1)

    httpClient := &http.Client{}

    resp, err := httpClient.Do(req)
    if err != nil {
        log.Fatal("Do: ", err)
        return
    }

    defer resp.Body.Close()

    byteArray, _ := ioutil.ReadAll(resp.Body)
    log.Println(string(byteArray))

}

2017/11/05 21:43:24 https://eastasia.api.cognitive.microsoft.com/face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,gender,glasses
2017/11/05 21:43:25 [{"faceId":"4e075f28-ce54-4844-ac63-a4a77b5da9ce","faceRectangle":{"top":64,"left":121,"width":152,"height":152},"faceAttributes":{"gender":"male","age":44.8,"glasses":"NoGlasses"}}]

※サンプル画像はネットより拝借しました。m(_ _)m

所感

料金プランかなんかで速度とか変わると良いです。なんか時間としてはそんなに早く感じていないので

go言語で画像を作成(編集)する【imagemagick】

ImageMagick

画像編集するライブラリで超優秀なやつ
文字列の設定なども可能
フォントは微妙

インストール(Mac

brew install ruby
brew install ImageMagick
brew install pkg-config
go get gopkg.in/gographics/imagick.v3/imagick

rubyは2.3以上
※imagickはimagemagickのインストールバージョンで切り替え

実装

sample2.go
package main

import (
    "gopkg.in/gographics/imagick.v3/imagick"
//    "fmt"
)

func main() {

    var err error

    imagick.Initialize()
    defer imagick.Terminate()
    mw := imagick.NewMagickWand()
    dw := imagick.NewDrawingWand()
    pw := imagick.NewPixelWand()
    defer mw.Destroy()

    // 短形を作成
    pw.SetColor("none")
    mw.NewImage(400, 300, pw)

    // フォント設定
    pw.SetColor("RGB(255, 0, 125)")
    dw.SetFillColor(pw)
    dw.SetFontSize(60)
    pw.SetColor("RGB(255, 0, 125)")
    dw.SetStrokeColor(pw)

    // テキスト設定
    dw.Annotation(25, 65, "Sample")

    // 短形の描画(塗りつぶしなし)
    pw.SetColor("RGB(100, 100, 100)")
    dw.SetStrokeColor(pw)
    dw.SetStrokeWidth(4)
    pw.SetColor("none")
    dw.SetFillColor(pw)
    dw.Rectangle(50, 150, 120, 250)
    dw.PushDrawingWand()

    // 描画
    mw.DrawImage(dw)

    // 合成用
    pw2 := imagick.NewPixelWand()
    mw2 := imagick.NewMagickWand()
    defer mw2.Destroy()
    pw2.SetColor("blue")
    mw2.NewImage(120, 100, pw2)
    // 指定の場所へ合成
    err = mw.CompositeImage(mw2, mw2.GetImageCompose(), true, 100, 100)
    if err != nil {
        panic(err)
    }

    // 出力フォーマット
    err = mw.SetFormat("png")
    if err != nil {
        panic(err)
    }

    // ファイルへ出力
    mw.WriteImage("text_shadow.png")
}

f:id:m_shige1979:20171029150935p:plain

所感

文字列を挿入できました(^^)
まあ、あまり画像を使うことはないですがとりあえず覚えておこうかと思います。

go言語で超シンプルな画像作成

画像を作成

短形の画像を作成する。

実装

sample1.go
package main

import (
    "log"
    "image"
    "image/jpeg"
    "image/color"
    "os"
)

var (
    x = 0
    y = 0
    width = 400
    height = 300
    quality = 100
)

func main() {
    log.Println("start")

    // 短形を作成する
    img := image.NewRGBA(image.Rect(x, y, width, height))
    // 短形に色を追加
    for i := img.Rect.Min.Y; i<img.Rect.Max.Y;i++ {
        for j := img.Rect.Min.X; j<img.Rect.Max.X; j++ {
            img.Set(j, i, color.RGBA{255, 255, 0, 0})
        }
    }

    // ファイルを作成し、終了時にクローズ
    file, _ := os.Create("sampleImage1.jpg")
    defer file.Close()

    err := jpeg.Encode(file, img, &jpeg.Options{quality});
    if err != nil {
        log.Println(err)
    }

    log.Println("end")
}

結果
f:id:m_shige1979:20171029133049p:plain

所感

文字列が入力してみたいけどネットで探したけど見つからない…
探してもう少し探してみる

go言語でflagを使用したパラメータ指定を行う

flagパッケージ

./sample1 -user hogehoge

みたいな感じで項目名にあったパラメータを渡す処理
http://golang-jp.org/pkg/flag/

とにかく実装

sample1.go
package main

import (
    "log"
    "flag"
    "os"
)

// 引数取得エリア
type ParamItem struct {
    Url   string
    Count int
    User  string
    Pass  string
}

// 引数を指定して値を受け取る処理
func main() {
    // 処理開始
    log.Println("start")

    param := new(ParamItem)

    //
    flagObj := flag.NewFlagSet(os.Args[0], flag.ExitOnError)

    // 引数を登録
    flagObj.StringVar(&param.Url, "url", "", "URLを設定してください。")
    flagObj.StringVar(&param.User, "user", "", "ユーザ名を設定してください。")
    flagObj.StringVar(&param.Pass, "pass", "", "パスワードを設定してください。")

    // パース処理
    flagObj.Parse(os.Args[1:])
    for 0 < flagObj.NArg() {
        flagObj.Parse(flagObj.Args()[1:])
    }

    log.Println("url  = " + param.Url)
    log.Println("user = " + param.User)
    log.Println("pass = " + param.Pass)

    // 処理終了
    log.Println("end")
}

$ go run sample1.go -url http://hogehoge.com -user aaa -pass 1234
2017/10/28 17:29:07 start
2017/10/28 17:29:07 url  = http://hogehoge.com
2017/10/28 17:29:07 user = aaa
2017/10/28 17:29:07 pass = 1234
2017/10/28 17:29:07 end
$

ヘルプコマンドの場合

$ go run sample1.go -help
2017/10/28 17:29:46 start
  -pass string
    	パスワードを設定してください。
  -url string
    	URLを設定してください。
  -user string
    	ユーザ名を設定してください。
exit status 2
$

順番ってキー名の昇順?

所感

項目名と連動するので引数で何が必要かなどの指定を用意しやすい。
設定ファイルでの読み込みと合わせて行えば役に立ちそう

go言語で設定ファイルを読み込み2(別パッケージにして扱う)

1つのファイルの場合

はメンテしづらいので分割する

ファイル構成

.
├── config
│   └── appconfig.go
├── config.json
└── sample2.go

こんな感じ

実装

config.json
{
    "url": "http://hogehoge.com",
    "count": 100,
    "user": "hoge",
    "pass": "foo"
}
config/appconfig.go
package config

import (
    "io/ioutil"
    "encoding/json"
)

// 構造体定義
type Config struct {
    Url   string  `json:"url"`
    Count int     `json:"count"`
    User  string  `json:"user"`
    Pass  string  `json:"pass"`
}

// configファイルを読み込み構造体へ割当
func Read(filename string) (*Config, error) {

    // 構造体を定義
    c := new(Config)

    // 設定ファイルを読み込む
    jsonString, err := ioutil.ReadFile(filename)
    if err != nil {
        // エラー
        return c, err
    }

    // 設定
    err = json.Unmarshal(jsonString, c)
    if err != nil {
        // エラー
        return c, err
    }

    // 正常
    return c, nil
}
sample2.go
package main

import (
    "log"
    "os"
    "strconv"
    "./config"
)

// jsonの設定ファイルを読み込むサンプル
func main() {
    // 処理開始
    log.Println("start")

    // 構造体へconfigの結果を設定
    c, err := config.Read("config.json")
    if err != nil {
        log.Println(err)
        os.Exit(1)
    }

    // 結果出力
    log.Println("url   = " + c.Url)
    log.Println("count = " + strconv.Itoa(c.Count))
    log.Println("user  = " + c.User)
    log.Println("pass  = " + c.Pass)

    // 処理終了
    log.Println("end")
}

所感

うん、まあそれなりにスッキリした感じです。
構造体の場合は値渡しか参照渡しとなるかをきちんと考える必要がある

go言語でjson形式の設定ファイルを読み込む

実行する際の変数の外出

設定ファイルにして配置しておくとやりやすいので対応する。

前提

設定ファイルはjson

実装

config.json
{
    "url": "http://hogehoge.com",
    "count": 100,
    "user": "hoge",
    "pass": "foo"
}
sample1.go
package main

import (
    "log"
    "os"
    "io/ioutil"
    "encoding/json"
    "strconv"
)

// jsonの設定ファイルを読み込むサンプル
func main() {
    // 処理開始
    log.Println("start")

    jsonString, err := ioutil.ReadFile("config.json")
    if err != nil {
        log.Println(err)
        os.Exit(1)
    }

    // config.jsonの中身を出力
    // そのままだとbyteデータになるのでstringに変換
    log.Println(string(jsonString))

    // 構造体定義
    type Config struct {
        Url   string  `json:"url"`
        Count int     `json:"count"`
        User  string  `json:"user"`
        Pass  string  `json:"pass"`
    }

    // 設定変数用意
    c := new(Config)

    // 設定
    err = json.Unmarshal(jsonString, c)
    if err != nil {
        log.Println(err)
        os.Exit(2)
    }

    // 結果出力
    log.Println("url   = " + c.Url)
    log.Println("count = " + strconv.Itoa(c.Count))
    log.Println("user  = " + c.User)
    log.Println("pass  = " + c.Pass)

    // 処理終了
    log.Println("end")
}

$ go run sample1.go
2017/10/28 14:32:33 start
2017/10/28 14:32:33 {
    "url": "http://hogehoge.com",
    "count": 100,
    "user": "hoge",
    "pass": "foo"
}


2017/10/28 14:32:33 url   = http://hogehoge.com
2017/10/28 14:32:33 count = 100
2017/10/28 14:32:33 user  = hoge
2017/10/28 14:32:33 pass  = foo
2017/10/28 14:32:33 end
$

注意点

構造体に設定する際はフィールドの項目は外部公開できるように1文字目を大文字にしておくこと
そうしないと構造体のデータに設定されてくれない