| | |
| | | */ |
| | | import "C" |
| | | import ( |
| | | "errors" |
| | | "unsafe" |
| | | |
| | | "basic.com/libgowrapper/sdkstruct.git" |
| | | "basic.com/pubsub/protomsg.git" |
| | | "github.com/gogo/protobuf/proto" |
| | | ) |
| | | |
| | | // SDKFace sdk |
| | | type SDKFace struct { |
| | | handle unsafe.Pointer |
| | | detector bool |
| | | extractor bool |
| | | propertizer bool |
| | |
| | | } |
| | | |
| | | // NewSDK sdk |
| | | func NewSDK(fn func(...interface{})) interface{} { |
| | | h := C.create_sdkface() |
| | | if h == nil { |
| | | return nil |
| | | } |
| | | func NewSDK(fn func(...interface{})) *SDKFace { |
| | | |
| | | return &SDKFace{ |
| | | handle: h, |
| | | detector: false, |
| | | extractor: false, |
| | | propertizer: false, |
| | |
| | | } |
| | | |
| | | // Free free |
| | | func Free(i interface{}) { |
| | | s := i.(*SDKFace) |
| | | if s != nil && s.handle != nil { |
| | | C.release(s.handle) |
| | | } |
| | | func (s *SDKFace) Free() { |
| | | C.c_api_release() |
| | | } |
| | | |
| | | func (s *SDKFace) printLog(l ...interface{}) { |
| | |
| | | } |
| | | |
| | | // Detector detector |
| | | func Detector(i interface{}, minFaces, rollAngles, threadMax, gpu int) bool { |
| | | s := i.(*SDKFace) |
| | | func (s *SDKFace) Detector(minFaces, rollAngle, threadMax, gpu int) bool { |
| | | |
| | | if s.detector { |
| | | return true |
| | | } |
| | | ret := C.init_detector(s.handle, C.int(minFaces), C.int(rollAngles), C.int(threadMax), C.int(gpu)) |
| | | |
| | | ret := C.c_api_face_detector_init(C.int(threadMax), C.int(gpu), C.int(minFaces), C.int(rollAngle)) |
| | | |
| | | if ret <= 0 { |
| | | s.printLog("->face--> CREATE Detector ERROR") |
| | | s.printLog("->face--> CREATE Detector ERROR: ", ret) |
| | | return false |
| | | } |
| | | s.printLog("->face--> CREATE Detector Threads: ", threadMax, " GPU:", gpu) |
| | | |
| | | s.detector = true |
| | | return true |
| | | } |
| | | |
| | | // Extractor ext |
| | | func Extractor(i interface{}, threadMax, gpu int) bool { |
| | | s := i.(*SDKFace) |
| | | func (s *SDKFace) Extractor(threadMax, gpu int) bool { |
| | | |
| | | if s.extractor { |
| | | return true |
| | | } |
| | | ret := C.init_extractor(s.handle, C.int(threadMax), C.int(gpu)) |
| | | ret := C.c_api_face_extractor_init(C.int(threadMax), C.int(gpu)) |
| | | if ret <= 0 { |
| | | s.printLog("->face--> CREATE Extractor ERROR") |
| | | s.printLog("->face--> CREATE Extractor ERROR: ", ret) |
| | | return false |
| | | } |
| | | s.printLog("->face--> CREATE Extractor Threads: ", threadMax, " GPU:", gpu) |
| | | |
| | | s.extractor = true |
| | | return true |
| | | } |
| | | |
| | | // Propertizer prop |
| | | func Propertizer(i interface{}, threadMax int) bool { |
| | | s := i.(*SDKFace) |
| | | func (s *SDKFace) Propertizer(threadMax int) bool { |
| | | |
| | | if s.propertizer { |
| | | return true |
| | | } |
| | | ret := C.init_propertizer(s.handle, C.int(threadMax)) |
| | | ret := C.c_api_face_property_init(C.int(threadMax)) |
| | | if ret <= 0 { |
| | | s.printLog("->face--> CREATE Propertizer ERROR") |
| | | s.printLog("->face--> CREATE Propertizer ERROR: ", ret) |
| | | return false |
| | | } |
| | | s.printLog("->face--> CREATE Propertizer Threads: ", threadMax) |
| | | |
| | | s.propertizer = true |
| | | return true |
| | | } |
| | | |
| | | // Tracker track |
| | | func Tracker(i interface{}, w, h, maxFaces, interval, sampleSize, threadMax, gpu int) bool { |
| | | s := i.(*SDKFace) |
| | | if s.tracker { |
| | | return s.tracker |
| | | } |
| | | ret := C.init_tracker(s.handle, C.int(w), C.int(h), C.int(maxFaces), C.int(interval), C.int(sampleSize), C.int(threadMax), C.int(gpu)) |
| | | func (s *SDKFace) Tracker(w, h, maxFaces, interval, sampleSize, threadMax, gpu int) bool { |
| | | |
| | | if s.tracker { |
| | | return true |
| | | } |
| | | ret := C.c_api_face_tracker_init(C.int(threadMax), C.int(gpu), C.int(w), C.int(h), C.int(maxFaces), C.int(interval), C.int(sampleSize)) |
| | | if ret <= 0 { |
| | | s.printLog("->face--> CREATE Tracker ERROR") |
| | | s.printLog("->face--> CREATE Tracker ERROR: ", ret) |
| | | return false |
| | | } |
| | | s.tracker = true |
| | |
| | | } |
| | | |
| | | // Detect det |
| | | func Detect(s *SDKFace, data []byte, w, h, c int, ch int) []sdkstruct.CFacePos { |
| | | func (s *SDKFace) Detect(data []byte, w, h, c int, ch int) []sdkstruct.CFacePos { |
| | | if !s.detector { |
| | | return nil |
| | | } |
| | | |
| | | var cfpos unsafe.Pointer |
| | | var count C.int |
| | | ret := C.detect(s.handle, unsafe.Pointer(&data[0]), C.int(w), C.int(h), C.int(c), C.int(ch), &cfpos, &count) |
| | | if ret > 0 { |
| | | return CFacePosArrayToGoArray(cfpos, int(count)) |
| | | cfpos := C.c_api_face_detect(&count, (*C.uchar)(unsafe.Pointer(&data[0])), C.int(w), C.int(h), C.int(ch)) |
| | | if cfpos != nil { |
| | | defer C.free(unsafe.Pointer(cfpos)) |
| | | return CFacePosArrayToGoArray(unsafe.Pointer(cfpos), int(count)) |
| | | } |
| | | s.printLog("->face--> Detect No One, Ret: ", ret) |
| | | |
| | | s.printLog("->face--> Detect No One") |
| | | return nil |
| | | } |
| | | |
| | | // Extract extract |
| | | func Extract(s *SDKFace, fpos sdkstruct.CFacePos, data []byte, w, h, c int, ch int) []byte { |
| | | |
| | | pos := (*C.cFacePos)(unsafe.Pointer(&fpos)) |
| | | |
| | | //(void *handle, const cFacePos *pos, const void*data, const int w, const int h, const int c, const int chan, void **feat, int *featLen); |
| | | var feat unsafe.Pointer |
| | | var featLen C.int |
| | | ret := C.extract(s.handle, pos, unsafe.Pointer(&data[0]), C.int(w), C.int(h), C.int(c), C.int(ch), &feat, &featLen) |
| | | if ret > 0 { |
| | | return C.GoBytes(feat, featLen) |
| | | func (s *SDKFace) Extract(fpos sdkstruct.CFacePos, data []byte, w, h, c int, ch int) []byte { |
| | | if !s.extractor { |
| | | return nil |
| | | } |
| | | s.printLog("->face--> Extract Nothing, Ret: ", ret) |
| | | s.printLog("->face--> facepos: ", fpos) |
| | | |
| | | var featLen C.int |
| | | pos := (*C.cFacePos)(unsafe.Pointer(&fpos)) |
| | | if pos == nil { |
| | | return nil |
| | | } |
| | | |
| | | p := C.c_api_face_extract(&featLen, pos, (*C.uchar)(unsafe.Pointer(&data[0])), C.int(w), C.int(h), C.int(ch)) |
| | | if p != nil { |
| | | defer C.free(unsafe.Pointer(p)) |
| | | return C.GoBytes(unsafe.Pointer(p), featLen) |
| | | } |
| | | s.printLog("->face--> Extract Nothing") |
| | | return nil |
| | | } |
| | | |
| | | // Compare face compare |
| | | func Compare(i interface{}, feat1 []byte, feat2 []byte) float32 { |
| | | s := i.(*SDKFace) |
| | | func (s *SDKFace) Compare(feat1 []byte, feat2 []byte) float32 { |
| | | |
| | | if s.extractor { |
| | | return 0 |
| | | } |
| | | |
| | | res := C.compare(s.handle, (*C.uchar)(unsafe.Pointer(&feat1[0])), (*C.uchar)(unsafe.Pointer(&feat2[0]))) |
| | | res := C.c_api_face_compare((*C.uchar)(unsafe.Pointer(&feat1[0])), (*C.uchar)(unsafe.Pointer(&feat2[0]))) |
| | | return float32(res) |
| | | } |
| | | |
| | | // Propertize prop |
| | | func Propertize(s *SDKFace, fpos sdkstruct.CFacePos, data []byte, w, h, c int, ch int) *sdkstruct.CThftResult { |
| | | func (s *SDKFace) Propertize(fpos sdkstruct.CFacePos, data []byte, w, h, c int, ch int) sdkstruct.CThftResult { |
| | | if !s.propertizer { |
| | | return nil |
| | | return sdkstruct.CThftResult{Age: 0} |
| | | } |
| | | |
| | | pos := (*C.cFacePos)(unsafe.Pointer(&fpos)) |
| | | |
| | | var thft unsafe.Pointer |
| | | ret := C.propertize(s.handle, pos, unsafe.Pointer(&data[0]), C.int(w), C.int(h), C.int(c), C.int(ch), &thft) |
| | | if ret == 0 { |
| | | gothft := *(*sdkstruct.CThftResult)(thft) |
| | | C.free(thft) |
| | | return &gothft |
| | | } |
| | | s.printLog("->face--> Propertize Nothing, Ret: ", ret) |
| | | return nil |
| | | result := C.c_api_face_property(pos, (*C.uchar)(unsafe.Pointer(&data[0])), C.int(w), C.int(h), C.int(ch)) |
| | | s.printLog("->face--> Propertize") |
| | | return *(*sdkstruct.CThftResult)(unsafe.Pointer(&result)) |
| | | } |
| | | |
| | | // CFaceInfoArrayToGoArray convert cFaceInfo array to go |
| | |
| | | } |
| | | |
| | | // Track track |
| | | func Track(s *SDKFace, data []byte, w, h, c int, ch int) []sdkstruct.CFaceInfo { |
| | | func (s *SDKFace) Track(data []byte, w, h, c int, ch int) []sdkstruct.CFaceInfo { |
| | | if !s.tracker { |
| | | return nil |
| | | } |
| | |
| | | //img, const int chan, void **fInfo, int *fcnt); |
| | | |
| | | var fCount C.int |
| | | var finfos unsafe.Pointer |
| | | ret := C.track(s.handle, unsafe.Pointer(&data[0]), C.int(w), C.int(h), C.int(c), C.int(ch), &finfos, &fCount) |
| | | |
| | | if ret > 0 { |
| | | faces := CFaceInfoArrayToGoArray(finfos, int(fCount)) |
| | | //if len(faces) > 0{ |
| | | // fmt.Println("faces detected:", len(faces)) |
| | | //} |
| | | return faces |
| | | cFinfo := C.c_api_face_track(&fCount, (*C.uchar)(unsafe.Pointer(&data[0])), C.int(w), C.int(h), C.int(ch)) |
| | | // fmt.Println("cFinfo detected:", cFinfo) |
| | | if cFinfo == nil { |
| | | return nil |
| | | } |
| | | return nil |
| | | defer C.free(unsafe.Pointer(cFinfo)) |
| | | faces := CFaceInfoArrayToGoArray(unsafe.Pointer(cFinfo), int(fCount)) |
| | | return faces |
| | | } |
| | | |
| | | // FaceInfo2FacePos info -> pos |
| | |
| | | } |
| | | |
| | | // TrackerResize init face tracker |
| | | func TrackerResize(i interface{}, w, h, ch int) bool { |
| | | s := i.(*SDKFace) |
| | | func (s *SDKFace) TrackerResize(w, h, ch int) int { |
| | | |
| | | if !s.tracker { |
| | | s.printLog("->face--> TrackerResize Failed, No Tracker Init") |
| | | return false |
| | | return -1 |
| | | } |
| | | ret := C.resize(s.handle, C.int(w), C.int(h), C.int(ch)) |
| | | if ret == 1 { |
| | | return true |
| | | } |
| | | s.printLog("->face--> TrackerResize Failed, Ret: ", ret, " SDK Channel: ", ch, " Size: ", w, "x", h) |
| | | return false |
| | | return int(C.c_api_face_track_resize(C.int(ch), C.int(w), C.int(h))) |
| | | } |
| | | |
| | | // Run run |
| | | func Run(i interface{}, data []byte, w, h, c, dchan int) []sdkstruct.CFaceResult { |
| | | func (s *SDKFace) Run(data []byte, w, h, c, dchan int) (int, []byte, error) { |
| | | if data == nil || w <= 0 || h <= 0 { |
| | | return nil |
| | | return 0, nil, errors.New("->face--> Face Input Image Error") |
| | | } |
| | | |
| | | s := i.(*SDKFace) |
| | | |
| | | if !s.tracker || !s.extractor || !s.propertizer { |
| | | return nil |
| | | return 0, nil, errors.New("->face--> Face SDK No Init Correctly") |
| | | } |
| | | |
| | | channel := c |
| | |
| | | channel = 3 |
| | | } |
| | | |
| | | // if !TrackerResize(i, w, h, dchan) { |
| | | // return nil |
| | | // } |
| | | |
| | | var fInfo []sdkstruct.CFaceInfo |
| | | |
| | | fInfo = Track(s, data, w, h, c, dchan) |
| | | fInfo = s.Track(data, w, h, c, dchan) |
| | | if len(fInfo) == 0 { |
| | | return 0, nil, errors.New("->face--> Face Track No One") |
| | | } |
| | | |
| | | var faces []sdkstruct.CFaceResult |
| | | //将sdk返回值转换成protomsg类型 |
| | | var faces []*protomsg.ResultFaceDetect |
| | | |
| | | for _, d := range fInfo { |
| | | |
| | | //运行sd |
| | | dec := FaceInfo2FacePos(d) |
| | | prop := Propertize(s, dec, data, w, h, c, dchan) |
| | | feat := Extract(s, dec, data, w, h, c, dchan) |
| | | p := s.Propertize(dec, data, w, h, c, dchan) |
| | | feat := s.Extract(dec, data, w, h, c, dchan) |
| | | |
| | | result := sdkstruct.CFaceResult{ |
| | | Info: d, |
| | | Prop: *prop, |
| | | Feat: feat, |
| | | } |
| | | faces = append(faces, result) |
| | | /// filter rules |
| | | // sdkid := rMsg.Msg.Tasklab.Sdkinfos[rMsg.Msg.Tasklab.Index].Ipcid |
| | | // size := (d.RcFace.Right - d.RcFace.Left) * (d.RcFace.Bottom - d.RcFace.Top) |
| | | // angle := d.FAngle |
| | | // if !filter(rMsg.Msg.Tasklab.Taskid, sdkid, angle.Confidence, float32(angle.Yaw), int(size)) { |
| | | // continue |
| | | // } |
| | | /// filter rules |
| | | |
| | | prop := (*protomsg.ThftResult)(unsafe.Pointer(&p)) |
| | | fpos := tconvert2ProtoFacePos(d) |
| | | |
| | | //组成结果并序列化 |
| | | res := &protomsg.ResultFaceDetect{Pos: fpos, Result: prop, Feats: feat} |
| | | faces = append(faces, res) |
| | | |
| | | } |
| | | facePos := protomsg.ParamFacePos{Faces: faces} |
| | | d, e := proto.Marshal(&facePos) |
| | | |
| | | return faces |
| | | return len(faces), d, e |
| | | } |
| | | |
| | | func tconvert2ProtoFacePos(dec sdkstruct.CFaceInfo) *protomsg.FacePos { |
| | | |
| | | crect := dec.RcFace |
| | | rect := protomsg.Rect{Left: crect.Left, Top: crect.Top, Right: crect.Right, Bottom: crect.Bottom} |
| | | leftEye := (*protomsg.Point)(unsafe.Pointer(&dec.PtLeftEye)) |
| | | rightEye := (*protomsg.Point)(unsafe.Pointer(&dec.PtRightEye)) |
| | | mouth := (*protomsg.Point)(unsafe.Pointer(&dec.PtMouth)) |
| | | nose := (*protomsg.Point)(unsafe.Pointer(&dec.PtNose)) |
| | | angle := (*protomsg.FaceAngle)(unsafe.Pointer(&dec.FAngle)) |
| | | faceID := uint64(dec.NFaceID) |
| | | |
| | | facialData := dec.PFacialData[:512] |
| | | |
| | | // facialData := make([]byte, 512) |
| | | // copy(facialData[:], dec.PFacialData[:512]) |
| | | |
| | | return &protomsg.FacePos{ |
| | | RcFace: &rect, |
| | | PtLeftEye: leftEye, |
| | | PtRightEye: rightEye, |
| | | PtMouth: mouth, |
| | | PtNose: nose, |
| | | FAngle: angle, |
| | | Quality: dec.NQuality, |
| | | FacialData: facialData, |
| | | FaceID: faceID, |
| | | } |
| | | } |