Prettifying the results

The program prints the results. It looks something as follows:

 Error: <nil>
[]facebox.Face{facebox.Face{Rect:facebox.Rect{Top:221, Left:303, Width:75, Height:75}, ID:"", Name:"", Matched:false, Confidence:0, Faceprint:""}}

This is a rather boring result to be printed on the terminal output. We live in the age of GUIs now! So let's draw our results.

As a result, we want the window to show whatever the webcam is showing. Then, when a key is pressed, the image is captured, and processed by MachineBox. If a face is found, a rectangle should be drawn around it. If the face is recognized as MC Hot Dog, then label the box HotDog, followed by the confidence. Otherwise, the box should be labelled Not HotDog. The code for this looks a bit convoluted:

     // open webcam
webcam, err := gocv.VideoCaptureDevice(0)
if err != nil {
log.Fatal(err)
}
defer webcam.Close()

// prepare image matrix
img := gocv.NewMat()
defer img.Close()

// open display window
window := gocv.NewWindow("Face Recognition")
defer window.Close()

var recognized bool
for {
if !recognized {
if ok := webcam.Read(&img); !ok {
log.Fatal("Failed to read image")
}
}

window.IMShow(img)
if window.WaitKey(1) >= 0 {
if !recognized {
recognize(&img, box)
recognized = true
continue
} else {
break
}
}
}

But if we break it down, we can see that the code in the main function can be split into two parts. The first part deals with opening a webcam and creating a window to display the image. A more complete account of this is covered in the previous chapter.

In particular, let's turn our focus to the infinite loop:

     for {
if !recognized {
if ok := webcam.Read(&img); !ok {
log.Fatal("Failed to read image")
}
}

window.IMShow(img)
if window.WaitKey(1) >= 0 {
if !recognized {
recognize(&img, box)
recognized = true
} else {
break
}
}
}

What this says is simply this: first check whether the recognition process has been done. If it hasn't, grab an image from the webcam, and then show the image using window.IMShow(img). This constitutes the main loop—the webcam will continuously capture an image and then immediately display it in the window.

But what happens when a key is pressed? The block of code that follows says to wait for a keyboard event for 1 millisecond. If there is an event, any event at all, we check whether the image had previously been recognized. If not, call recognize, passing in the captured image from the matrix, and the MachineBox client. Then we set the recognized flag as true. Thus, upon the next key press, we exit the program.

recognize is where the meat of the drawing is done. If you have gone through the previous chapter, this should be quite familiar to you already. Otherwise, here's how recognize looks:

 
var blue = color.RGBA{0, 0, 255, 0}

func recognize(img *gocv.Mat, box *facebox.Client) (err error) {
var buf bytes.Buffer
prop, _ := img.ToImage()
if err = jpeg.Encode(&buf, prop, nil); err != nil {
log.Fatal("Failed to encode image as JPG %v", err)
}

// rd := bytes.NewReader(prop.(*image.RGBA).Pix)
faces, err := box.Check(&buf)
// fmt.Println(err)
// fmt.Printf("%#v ", faces)

for _, face := range faces {
// draw a rectangle
r := rect2rect(face.Rect)
gocv.Rectangle(img, r, blue, 3)

lbl := "Not HotDog"
if face.Matched {
lbl = fmt.Sprintf("%v %1.2f%%", face.Name, face.Confidence*100)
}
size := gocv.GetTextSize(lbl, gocv.FontHersheyPlain, 1.2, 2)
pt := image.Pt(r.Min.X+(r.Min.X/2)-(size.X/2), r.Min.Y-2)
gocv.PutText(img, lbl, pt, gocv.FontHersheyPlain, 1.2, blue, 2)
}
return nil
}

Here, we see the familiar code used to first encode the image as a JPEG, and then send it to the MachineBox client for classification. Then, for each face found, we draw a blue rectangle around it. facebox.Face is defined as follows:

 type Face struct {
Rect Rect
ID string
Name string
Matched bool
Confidence float64
Faceprint string
}

facebox.Face allows us to identify the faces, if they are matched, and the confidence level. So if there is a face found, these fields would be accessible to the programmer.

But first, we must solve the issue of rectangles. MachineBox does not use the same definition of rectangles as image.Rectangle, which is found in the standard library.

Thus, a helper function to convert facebox.Rect into image.Rectangle is required:

 func rect2rect(a facebox.Rect) image.Rectangle {
return image.Rect(a.Left, a.Top, a.Left+a.Width, a.Top+a.Height)
}

There are only a handful of ways to define a rectangle. Conversion among the two different types is trivial.

After the rectangle has been drawn, a label is written. If the face is recognized as MC Hot Dog, we'll label it as HotDog. MachineBox also provides a confidence score, which is a number between 0 and 1 on whether a face is HotDog or Not HotDog. So we'll draw that into the label as well.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.163.197