Golang : Another camera capture GUI application with GTK and OpenCV
For those that prefer to use GTK over Qt, this is another tutorial/example to show you how to create a GUI application similar to Apple's PhotoBooth with GTK instead of Qt.
In this example, we will create a "floating" toolbar similar to Photoshop's floating toolbar concept. This is purely for performance reason and allow us to skip the transformation of OpenCV's IplImage(Intel Image Processing Library) to QImage or GDK Pixbuf.
We will use the Golang-GTK binding at https://mattn.github.io/go-gtk/. If you prefer to use https://github.com/gotk3/gotk3, please change the code example that follows.
To get the code example below running, first please
>brew install gtk
or
>brew install gtk+3
and
>go get -u https://mattn.github.io/go-gtk
>go get -u github.com/lazywei/go-opencv/opencv
Here you go!
package main
import (
"fmt"
"os"
"strconv"
"strings"
"github.com/lazywei/go-opencv/opencv"
"github.com/mattn/go-gtk/glib"
"github.com/mattn/go-gtk/gtk"
)
var (
win = new(opencv.Window)
webCamera = new(opencv.Capture)
statusbar = new(gtk.Statusbar)
snapshotFileName string
width, height int
sliderPos int
filterOn = true
snapPhoto = false
)
func savePhoto(img *opencv.IplImage) {
// snap photo
if snapPhoto {
fmt.Println("Snapshot save to : ", snapshotFileName)
// params - to set jpeg quality
// but unable to pass params []int slice to opencv...
os.Remove(snapshotFileName) // remove previous save file - ignoring error!
opencv.SaveImage(snapshotFileName, img, opencv.CV_IMWRITE_JPEG_QUALITY)
snapPhoto = false // reset to false again
}
}
// from https://github.com/lazywei/go-opencv/blob/master/samples/webcam.go
func applyFilters(img *opencv.IplImage) {
w := img.Width()
h := img.Height()
// Create the output image
cedge := opencv.CreateImage(w, h, opencv.IPL_DEPTH_8U, 3)
defer cedge.Release()
// Convert to grayscale
gray := opencv.CreateImage(w, h, opencv.IPL_DEPTH_8U, 1)
edge := opencv.CreateImage(w, h, opencv.IPL_DEPTH_8U, 1)
defer gray.Release()
defer edge.Release()
opencv.CvtColor(img, gray, opencv.CV_BGR2GRAY)
opencv.Smooth(gray, edge, opencv.CV_BLUR, 3, 3, 0, 0)
opencv.Not(gray, edge)
// Run the edge detector on grayscale
opencv.Canny(gray, edge, float64(sliderPos), float64(sliderPos*3), 3)
opencv.Zero(cedge)
// copy edge points
opencv.Copy(img, cedge, edge)
// update here. if update in the for loop... the image frames will be corrupted.
win.ShowImage(cedge)
savePhoto(cedge)
}
func processFrameAndUpdate() {
for {
if webCamera.GrabFrame() {
IplImgFrame := webCamera.RetrieveFrame(1)
if IplImgFrame != nil {
// Have to make the image frame
// smaller, so that it does not blow up the GUI application.
IplImgFrame = opencv.Resize(IplImgFrame, 0, height-200, opencv.CV_INTER_LINEAR)
if filterOn == true {
applyFilters(IplImgFrame)
} else {
sliderPos = 0 // otherwise the save file will be blurred
win.ShowImage(IplImgFrame)
savePhoto(IplImgFrame)
}
// apply filters
//*IplImgFrame = applyFilters(IplImgFrame)
//win.ShowImage(IplImgFrame) -- will cause alien EMP attack on images. WTF!
}
}
}
}
func main() {
if len(os.Args) != 2 {
fmt.Printf("Usage : %s <save to filename>\n", os.Args[0])
os.Exit(0)
}
snapshotFileName = os.Args[1]
if !strings.HasSuffix(snapshotFileName, ".jpg") {
snapshotFileName += ".jpg"
}
fmt.Println("Will be saving snapshot image to : ", snapshotFileName)
// a new OpenCV window
win = opencv.NewWindow("Go-OpenCV camera feed for Gtk-GUI")
defer win.Destroy()
// activate webCamera
webCamera = opencv.NewCameraCapture(opencv.CV_CAP_ANY) // autodetect
if webCamera == nil {
panic("Unable to open camera")
}
defer webCamera.Release()
// get some data from camera
width = int(webCamera.GetProperty(opencv.CV_CAP_PROP_FRAME_WIDTH))
height = int(webCamera.GetProperty(opencv.CV_CAP_PROP_FRAME_HEIGHT))
fmt.Println("Camera width : ", width)
fmt.Println("Camera height : ", height)
// open up a new "pure" OpenCV window first
go processFrameAndUpdate() // goroutine to update feed from camera
// then our "floating" GTK toolbar
gtk.Init(nil)
window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
window.SetPosition(gtk.WIN_POS_CENTER)
window.SetTitle("Golang-GTK-OpenCV-AppleBooth-Example!")
window.SetIconName("gtk-dialog-info")
window.Connect("destroy", func(ctx *glib.CallbackContext) {
println("got destroy!", ctx.Data().(string))
gtk.MainQuit()
}, "Happy coding!")
vbox := gtk.NewVBox(false, 1)
//--------------------------------------------------------
// GtkVPaned
//--------------------------------------------------------
vpaned := gtk.NewVPaned()
vbox.Add(vpaned)
frame2 := gtk.NewFrame("Control panel with scroll bar and buttons(GUI) for OpenCV")
framebox2 := gtk.NewVBox(false, 1)
frame2.Add(framebox2)
//--------------------------------------------------------
// GtkScale
//--------------------------------------------------------
scaleHBox := gtk.NewHBox(false, 1)
scale := gtk.NewHScaleWithRange(0, 100, 1)
scale.Connect("value-changed", func() {
sliderPos = int(scale.GetValue())
statusbar.Push(statusbar.GetContextId("go-gtk"), "Position value : "+strconv.Itoa(sliderPos))
})
scaleHBox.Add(scale)
framebox2.PackStart(scaleHBox, false, false, 0)
vpaned.Pack2(frame2, false, false)
//--------------------------------------------------------
// GtkHBox
//--------------------------------------------------------
buttons := gtk.NewHBox(false, 1)
//--------------------------------------------------------
// GtkButton
//--------------------------------------------------------
button := gtk.NewButtonWithLabel("Take a snapshot!")
button.Clicked(func() {
snapPhoto = true
})
buttons.Add(button)
quitButton := gtk.NewButtonWithLabel("Quit")
quitButton.Clicked(func() {
gtk.MainQuit()
})
buttons.Add(quitButton)
framebox2.PackStart(buttons, false, false, 0)
//--------------------------------------------------------
// GtkVSeparator
//--------------------------------------------------------
vsep := gtk.NewVSeparator()
framebox2.PackStart(vsep, false, false, 0)
statusbar = gtk.NewStatusbar()
context_id := statusbar.GetContextId("go-gtk")
combos := gtk.NewHBox(false, 1)
//--------------------------------------------------------
// GtkStatusbar and GtkComboBox
//--------------------------------------------------------
combobox := gtk.NewComboBoxNewText()
combobox.AppendText("Yes")
combobox.AppendText("No")
combobox.SetActive(0) // yes
combobox.Connect("changed", func() {
println("value:", combobox.GetActiveText())
if combobox.GetActiveText() == "Yes" {
statusbar.Push(context_id, "Applying filter.")
filterOn = true
} else {
statusbar.Push(context_id, "Not applying filter.")
filterOn = false
}
})
combos.Add(combobox)
framebox2.PackStart(combos, false, false, 0)
//--------------------------------------------------------
// GtkStatusbar
//--------------------------------------------------------
framebox2.PackStart(statusbar, false, false, 0)
//--------------------------------------------------------
// Event
//--------------------------------------------------------
window.Add(vbox)
window.SetSizeRequest(400, 115)
window.ShowAll()
gtk.Main()
}
See also : Golang : GUI with Qt and OpenCV to capture image from camera
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+13.1k Golang : Generate Code128 barcode
+14.8k JavaScript/JQuery : Detect or intercept enter key pressed example
+35.8k Golang : How to split or chunking a file to smaller pieces?
+14.8k Golang : How to check if IP address is in range
+6.5k Golang : Find the longest line of text example
+20k nginx: [emerg] unknown directive "passenger_enabled"
+8.6k Golang : HTTP Routing with Goji example
+15k Golang : Find location by IP address and display with Google Map
+7k Golang : Example of custom handler for Gorilla's Path usage.
+7.7k Golang Hello World Example
+4.8k Linux : How to set root password in Linux Mint
+6.9k Golang : Get Alexa ranking data example