Permalink
Fetching contributors…
Cannot retrieve contributors at this time
133 lines (104 sloc) 2.89 KB
// What it does:
//
// This example detects how many fingers you hold up in front of the camera.
//
// How to run:
//
// go run ./cmd/hand-gestures/main.go 0
//
// +build example
package main
import (
"fmt"
"image"
"image/color"
"math"
"os"
"gocv.io/x/gocv"
)
const MinimumArea = 3000
func main() {
if len(os.Args) < 2 {
fmt.Println("How to run:\n\thand-gestures [camera ID]")
return
}
// parse args
deviceID := os.Args[1]
webcam, err := gocv.OpenVideoCapture(deviceID)
if err != nil {
fmt.Printf("Error opening video capture device: %v\n", deviceID)
return
}
defer webcam.Close()
window := gocv.NewWindow("Hand Gestures")
defer window.Close()
img := gocv.NewMat()
defer img.Close()
imgGrey := gocv.NewMat()
defer imgGrey.Close()
imgBlur := gocv.NewMat()
defer imgBlur.Close()
imgThresh := gocv.NewMat()
defer imgThresh.Close()
hull := gocv.NewMat()
defer hull.Close()
defects := gocv.NewMat()
defer defects.Close()
green := color.RGBA{0, 255, 0, 0}
fmt.Printf("Start reading device: %v\n", deviceID)
for {
if ok := webcam.Read(&img); !ok {
fmt.Printf("Device closed: %v\n", deviceID)
return
}
if img.Empty() {
continue
}
// cleaning up image
gocv.CvtColor(img, &imgGrey, gocv.ColorBGRToGray)
gocv.GaussianBlur(imgGrey, &imgBlur, image.Pt(35, 35), 0, 0, gocv.BorderDefault)
gocv.Threshold(imgBlur, &imgThresh, 0, 255, gocv.ThresholdBinaryInv+gocv.ThresholdOtsu)
// now find biggest contour
contours := gocv.FindContours(imgThresh, gocv.RetrievalExternal, gocv.ChainApproxSimple)
c := getBiggestContour(contours)
gocv.ConvexHull(c, &hull, true, false)
gocv.ConvexityDefects(c, hull, &defects)
var angle float64
defectCount := 0
for i := 0; i < defects.Rows(); i++ {
start := c[defects.GetIntAt(i, 0)]
end := c[defects.GetIntAt(i, 1)]
far := c[defects.GetIntAt(i, 2)]
a := math.Sqrt(math.Pow(float64(end.X-start.X), 2) + math.Pow(float64(end.Y-start.Y), 2))
b := math.Sqrt(math.Pow(float64(far.X-start.X), 2) + math.Pow(float64(far.Y-start.Y), 2))
c := math.Sqrt(math.Pow(float64(end.X-far.X), 2) + math.Pow(float64(end.Y-far.Y), 2))
// apply cosine rule here
angle = math.Acos((math.Pow(b, 2)+math.Pow(c, 2)-math.Pow(a, 2))/(2*b*c)) * 57
// ignore angles > 90 and highlight rest with dots
if angle <= 90 {
defectCount++
gocv.Circle(&img, far, 1, green, 2)
}
}
status := fmt.Sprintf("defectCount: %d", defectCount+1)
rect := gocv.BoundingRect(c)
gocv.Rectangle(&img, rect, color.RGBA{255, 255, 255, 0}, 2)
gocv.PutText(&img, status, image.Pt(10, 20), gocv.FontHersheyPlain, 1.2, green, 2)
window.IMShow(img)
if window.WaitKey(1) == 27 {
break
}
}
}
func getBiggestContour(contours [][]image.Point) []image.Point {
var area float64
index := 0
for i, c := range contours {
newArea := gocv.ContourArea(c)
if newArea > area {
area = newArea
index = i
}
}
return contours[index]
}