diff --git a/Makefile b/Makefile index 5a34b09..3206619 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ -all: +all: @./build.sh clean: @rm -f pigo install: all @cp pigo /usr/local/bin -uninstall: +uninstall: @rm -f /usr/local/bin/pigo package: @NOCOPY=1 ./build.sh package \ No newline at end of file diff --git a/wasm/Makefile b/wasm/Makefile index 7427b49..508edd3 100644 --- a/wasm/Makefile +++ b/wasm/Makefile @@ -20,7 +20,7 @@ wasm: serve: $(BROWSER) 'http://localhost:5000' - serve + go run http/serve.go clean: rm -f *.wasm diff --git a/wasm/canvas/canvas.go b/wasm/canvas/canvas.go index f14d20b..9bc34a2 100644 --- a/wasm/canvas/canvas.go +++ b/wasm/canvas/canvas.go @@ -228,13 +228,12 @@ func (c *Canvas) drawDetection(dets [][]int) { if c.flploc { flps := det.DetectLandmarkPoints(leftPupil, rightPupil) - c.ctx.Call("beginPath") c.ctx.Set("fillStyle", "rgb(0, 255, 0)") for _, flp := range flps { if len(flp) > 0 { col, row, scale = flp[1], flp[0], flp[2]/7 - c.ctx.Call("moveTo", row+flp[2]/7, col) + c.ctx.Call("moveTo", row, col) c.ctx.Call("arc", row, col, scale, 0, 2*math.Pi, false) } } diff --git a/wasm/detector/detector.go b/wasm/detector/detector.go index 334bcda..783c854 100644 --- a/wasm/detector/detector.go +++ b/wasm/detector/detector.go @@ -31,7 +31,7 @@ var ( func (d *Detector) UnpackCascades() error { p := pigo.NewPigo() - cascade, err = d.FetchCascade("https://raw.githubusercontent.com/esimov/pigo/master/cascade/facefinder") + cascade, err = d.ParseCascade("/cascade/facefinder") if err != nil { return errors.New("error reading the facefinder cascade file") } @@ -44,7 +44,7 @@ func (d *Detector) UnpackCascades() error { plc := pigo.NewPuplocCascade() - puplocCascade, err = d.FetchCascade("https://raw.githubusercontent.com/esimov/pigo/master/cascade/puploc") + puplocCascade, err = d.ParseCascade("/cascade/puploc") if err != nil { return errors.New("error reading the puploc cascade file") } @@ -54,7 +54,7 @@ func (d *Detector) UnpackCascades() error { return errors.New("error unpacking the puploc cascade file") } - flpcs, err = d.parseFlpCascades("https://raw.githubusercontent.com/esimov/pigo/master/cascade/lps/") + flpcs, err = d.parseFlpCascades("/cascade/lps/") if err != nil { return errors.New("error unpacking the facial landmark points detection cascades") } @@ -177,7 +177,7 @@ func (d *Detector) parseFlpCascades(path string) (map[string][]*FlpCascade, erro pl := pigo.NewPuplocCascade() for _, cascade := range cascades { - puplocCascade, err = d.FetchCascade(path + cascade) + puplocCascade, err = d.ParseCascade(path + cascade) if err != nil { d.Log("Error reading the cascade file: %v", err) } diff --git a/wasm/detector/fetch.go b/wasm/detector/fetch.go index 4c8963f..e868403 100644 --- a/wasm/detector/fetch.go +++ b/wasm/detector/fetch.go @@ -3,6 +3,9 @@ package detector import ( "errors" "fmt" + "io/ioutil" + "net/http" + "net/url" "syscall/js" ) @@ -74,6 +77,36 @@ func (d *Detector) FetchCascade(url string) ([]byte, error) { } } +// ParseCascade loads and parse the cascade file through the +// Javascript `location.href` method, using the `js/syscall` package. +// It will return the cascade file encoded into a byte array. +func (d *Detector) ParseCascade(path string) ([]byte, error) { + href := js.Global().Get("location").Get("href") + u, err := url.Parse(href.String()) + if err != nil { + return nil, err + } + u.Path = path + + resp, err := http.Get(u.String()) + if err != nil || resp.StatusCode != 200 { + return nil, errors.New(fmt.Sprintf("%v cascade file is missing", u.String())) + } + defer resp.Body.Close() + + buffer, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + uint8Array := js.Global().Get("Uint8Array").New(len(buffer)) + js.CopyBytesToJS(uint8Array, buffer) + + buff := make([]byte, uint8Array.Get("length").Int()) + js.CopyBytesToGo(buff, uint8Array) + + return buff, nil +} + // Log calls the `console.log` Javascript function func (d *Detector) Log(args ...interface{}) { d.window.Get("console").Call("log", args...) diff --git a/wasm/http/serve.go b/wasm/http/serve.go new file mode 100644 index 0000000..e40e3e6 --- /dev/null +++ b/wasm/http/serve.go @@ -0,0 +1,57 @@ +package main + +import ( + "log" + "net/http" + "path/filepath" +) + +// httpConn web server connection parameters +type httpConn struct { + address string + port string + root string + cascadeDir string +} + +func main() { + httpConn := &httpConn{ + address: "localhost", + port: "5000", + root: "./", + cascadeDir: "../cascade/", + } + c := NewConn(httpConn) + c.Init() +} + +// NewConn establish a new http connection +func NewConn(conn *httpConn) *httpConn { + return conn +} + +// Init listen and serves the connection endpoints +func (c *httpConn) Init() { + var err error + c.root, err = filepath.Abs(c.root) + if err != nil { + log.Fatalln(err) + } + + log.Printf("serving %s on %s:%s", c.root, c.address, c.port) + http.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir(c.root)))) + http.Handle("/cascade/", http.StripPrefix("/cascade/", http.FileServer(http.Dir(c.cascadeDir)))) + + handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + log.Print(r.RemoteAddr + " " + r.Method + " " + r.URL.String()) + http.DefaultServeMux.ServeHTTP(w, r) + }) + httpServer := http.Server{ + Addr: c.address + ":" + c.port, + Handler: handler, + } + err = httpServer.ListenAndServe() + if err != nil { + log.Fatalln(err) + } +}