├── .gitignore ├── LICENSE ├── README.md ├── face.go └── web ├── .idea ├── vcs.xml └── workspace.xml ├── css └── style.css ├── index.html ├── js ├── axios.min.js ├── axios.min.map ├── vue-image-upload-resize.js └── vue.min.js └── public ├── faceblur.jpg ├── lenna-bef.jpg └── lenna-res.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | deploy.prototxt 15 | res10_300x300_ssd_iter_140000.caffemodel 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Billy park 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-opencv-caffe-facedetect-blur 2 | Go & OpenCV & Caffe 기반 얼굴인식 & 얼굴 블러 처리하기 3 | 4 | # 이게 뭔가요? 5 | OpenCV 공부중에 주말 프로젝트로 만들어본 Go 언어 기반 얼굴인식 기능 및 블러 처리 프로그램입니다. 6 | 7 | 이미 학습되어 있는 Caffe 기반의 딥러닝 얼굴인식 모델을 활용하여 주어진 이미지에서 얼굴을 인식하고 인식된 얼굴 부분을 블러 처리하여 웹요청에 응답합니다. 8 | 9 | Go Gin 기반으로 웹 프론트에 용청에 응답을 처리 하고 프론트에서는 Vue.js & Axios 등으로 Go 서버에 이미지를 전송 하고 결과를 받아서 화면에 뿌려 줍니다. 10 | 11 | 이 소스는 MIT 라이센스로 자유롭게 활용할 수 있습니다. 12 | 13 | # 데모페이지 14 | 아래 링크에서 실행 데모를 볼 수 있습니다. 15 | [http://face.practical.kr](http://face.practical.kr) 16 | 17 | # 의존성 18 | * Go 언어 - [https://golang.org](https://golang.org/) 19 | * gocv.io/x/gocv 20 | * github.com/gin-gonic/gin 21 | * github.com/rs/xid 22 | * github.com/gin-contrib/static 23 | * Caffe Model - [https://github.com/opencv/opencv_3rdparty/raw/dnn_samples_face_detector_20170830/res10_300x300_ssd_iter_140000.caffemodel](https://github.com/opencv/opencv_3rdparty/raw/dnn_samples_face_detector_20170830/res10_300x300_ssd_iter_140000.caffemodel) 24 | * Prototext Config - [https://raw.githubusercontent.com/opencv/opencv/master/samples/dnn/face_detector/deploy.prototxt](https://raw.githubusercontent.com/opencv/opencv/master/samples/dnn/face_detector/deploy.prototxt) 25 | * Vue.js - [https://vuejs.org/](https://vuejs.org/) 26 | 27 | # 실행방법 28 | 29 | * Git Clone - [https://github.com/bipark/go-opencv-caffe-facedetect-blur.git](https://github.com/bipark/go-opencv-caffe-facedetect-blur.git) 30 | * GoCV 설치 - [https://gocv.io/getting-started](https://gocv.io/getting-started) 31 | * Caffe 모델 다운로드 32 | * Caffe Model - [https://github.com/opencv/opencv_3rdparty/raw/dnn_samples_face_detector_20170830/res10_300x300_ssd_iter_140000.caffemodel](https://github.com/opencv/opencv_3rdparty/raw/dnn_samples_face_detector_20170830/res10_300x300_ssd_iter_140000.caffemodel) 33 | * Prototext Config - [https://raw.githubusercontent.com/opencv/opencv/master/samples/dnn/face_detector/deploy.prototxt](https://raw.githubusercontent.com/opencv/opencv/master/samples/dnn/face_detector/deploy.prototxt) 34 | -------------------------------------------------------------------------------- /face.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "image" 6 | _ "image/color" 7 | "os" 8 | "path/filepath" 9 | 10 | "github.com/gin-contrib/static" 11 | "github.com/gin-gonic/gin" 12 | "github.com/rs/xid" 13 | "net/http" 14 | 15 | "gocv.io/x/gocv" 16 | ) 17 | 18 | var ( 19 | net gocv.Net 20 | fcount int 21 | ) 22 | 23 | // 얼굴인증 결과 처리 24 | func performDetection(frame *gocv.Mat, results gocv.Mat) { 25 | for i := 0; i < results.Total(); i += 7 { 26 | confidence := results.GetFloatAt(0, i+2) 27 | if confidence > 0.4 { 28 | left := int(results.GetFloatAt(0, i+3) * float32(frame.Cols())) 29 | top := int(results.GetFloatAt(0, i+4) * float32(frame.Rows())) 30 | right := int(results.GetFloatAt(0, i+5) * float32(frame.Cols())) 31 | bottom := int(results.GetFloatAt(0, i+6) * float32(frame.Rows())) 32 | 33 | imgFace := frame.Region(image.Rect(left, top, right, bottom)) 34 | fcount = fcount + 1 35 | gocv.GaussianBlur(imgFace, &imgFace, image.Pt(75, 75), 0, 0, gocv.BorderDefault) 36 | imgFace.Close() 37 | } 38 | } 39 | } 40 | 41 | func faceDetection(uid string) string { 42 | 43 | // 얼굴인식 초기값 44 | ratio := 1.0 45 | mean := gocv.NewScalar(104, 177, 123, 0) 46 | swapRGB := false 47 | 48 | // 업로드된 이미지를 읽어서... 49 | img := gocv.IMRead("./web/public/uploads/"+uid, gocv.ColorBGRAToBGR) 50 | if img.Empty() { 51 | return "Load Error" 52 | } 53 | blob := gocv.BlobFromImage(img, ratio, image.Pt(300, 300), mean, swapRGB, false) 54 | 55 | // 얼굴인식 56 | net.SetInput(blob, "") 57 | prob := net.Forward("") 58 | performDetection(&img, prob) 59 | 60 | prob.Close() 61 | blob.Close() 62 | 63 | // 결과를저장 64 | savename := "./web/public/results/" + uid + ".jpg" 65 | gocv.IMWrite(savename, img) 66 | 67 | return uid 68 | } 69 | 70 | func fileExists(filename string) bool { 71 | info, err := os.Stat(filename) 72 | if os.IsNotExist(err) { 73 | return false 74 | } 75 | return !info.IsDir() 76 | } 77 | 78 | func main() { 79 | 80 | // 폴더 없으면 만든다 81 | newpath1 := filepath.Join("./web/", "public") 82 | os.MkdirAll(newpath1, os.ModePerm) 83 | newpath2 := filepath.Join("./web/public", "uploads") 84 | os.MkdirAll(newpath2, os.ModePerm) 85 | newpath3 := filepath.Join("./web/public", "results") 86 | os.MkdirAll(newpath3, os.ModePerm) 87 | 88 | // 카페 모델 읽어들이기 89 | if !fileExists("res10_300x300_ssd_iter_140000.caffemodel") { 90 | fmt.Println("Face Detect Model Not Exist!") 91 | fmt.Println("Download : wget https://github.com/opencv/opencv_3rdparty/raw/dnn_samples_face_detector_20170830/res10_300x300_ssd_iter_140000.caffemodel") 92 | return 93 | } 94 | 95 | if !fileExists("deploy.prototxt") { 96 | fmt.Println("Face Detect Prototext Config Not Exist!") 97 | fmt.Println("Download : wget https://raw.githubusercontent.com/opencv/opencv/master/samples/dnn/face_detector/deploy.prototxt") 98 | return 99 | } 100 | 101 | // DNN 네트워크 생성 102 | net = gocv.ReadNet("res10_300x300_ssd_iter_140000.caffemodel", "deploy.prototxt") 103 | defer net.Close() 104 | 105 | net.SetPreferableBackend(gocv.NetBackendType(gocv.NetBackendDefault)) 106 | net.SetPreferableTarget(gocv.NetTargetType(gocv.NetTargetCPU)) 107 | 108 | // 웹 서버 생성 109 | gin.SetMode(gin.ReleaseMode) 110 | r := gin.Default() 111 | r.MaxMultipartMemory = 1 112 | r.Use(static.Serve("/", static.LocalFile("./web", false))) 113 | 114 | // 이미지 업로드 115 | r.POST("/api/image/add", func(c *gin.Context) { 116 | file, _ := c.FormFile("imageFile") 117 | 118 | uid := xid.New().String() 119 | filename := "./web/public/uploads/" + uid 120 | c.SaveUploadedFile(file, filename) 121 | 122 | // 얼굴인식 123 | fcount = 0 124 | location := faceDetection(uid) 125 | c.JSON(http.StatusOK, gin.H{ 126 | "location": location, 127 | "fcount": fcount, 128 | }) 129 | }) 130 | 131 | r.Run(":8082") 132 | } 133 | -------------------------------------------------------------------------------- /web/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /web/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 45 | 46 | 47 | 48 | vuetify 49 | plugins 50 | fileinput 51 | fileInput 52 | 53 | 54 | 55 | 57 | 58 | 70 | 71 | 72 | true 73 | 74 | true 75 | true 76 | 77 | 78 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 |