Golang : Tell color name with OpenCV example
Alright, I managed to train my 4-year-old son to learn color names. At this moment, he is able to name - red, green, blue and yellow colors. I was wondering if I can use OpenCV and Golang to recognize certain color names just by flashing a particular color in a certain position. For example, putting a blue toy in the region of interest and my program will be able to tell me that it detected blue color.
Such as:
Below is a code example on how to recognize a color name with OpenCV and Golang. It can detect red, green and blue colors. I'll leave it as an exercise for you to implement the yellow color recognition.
By the way, this is not really a good solution(but it gets the job done)....simply because it relies on too many "IF"
statements. The proper way should use a matrix and check if a color's decimal codes fall in between the range. However, at this stage, I just need a fast way to tell a color name with OpenCV.
Here you go!
package main
import (
"fmt"
"image"
"runtime"
"github.com/lazywei/go-opencv/opencv"
"github.com/mattn/go-gtk/glib"
"github.com/mattn/go-gtk/gtk"
)
var (
win = new(opencv.Window)
win2 = new(opencv.Window)
webCamera = new(opencv.Capture)
cascade = new(opencv.HaarCascade)
statusbar = new(gtk.Statusbar)
snapshotFileName string
width, height int
filterOn = true
label *image.RGBA
opencvLabel *opencv.IplImage
whiteColor = opencv.NewScalar(255, 255, 255, 255) // (blue, green, red, alpha)
greenColor = opencv.NewScalar(170, 255, 102, 255) // (blue, green, red, alpha)
blueColor = opencv.NewScalar(255, 0, 0, 255) // (blue, green, red, alpha)
redColor = opencv.NewScalar(0, 0, 255, 255) // (blue, green, red, alpha)
blackColor = opencv.NewScalar(0, 0, 0, 255) // (blue, green, red, alpha)
horizontalScale = float32(0.5)
verticalScale = float32(0.5)
shear = float32(1.0)
thickness = 1
lineType = 8
textFont = opencv.InitFont(opencv.CV_FONT_HERSHEY_SIMPLEX, horizontalScale, verticalScale, shear, thickness, lineType)
)
func detectColor(img *opencv.IplImage) {
// highlight our region of interest
opencv.Rectangle(img,
opencv.Point{100, 100},
opencv.Point{120, 120},
greenColor, 3, 4, 0)
// we want to extract the BGRA values
// from the ROI. Take the middle point
scalar := img.Get2D(110, 110)
//fmt.Println(scalar.Val())
scalarArray := scalar.Val()
//fmt.Println(scalarArray)
Bchannel := scalarArray[0]
Gchannel := scalarArray[1]
Rchannel := scalarArray[2]
Achannel := scalarArray[3]
fmt.Println("B,G,R,A : ", Bchannel, Gchannel, Rchannel, Achannel)
// so, we can get the B,G,R,A values....time to detect the color
// but let's ignore the Alpha channel for the moment.
IsBlue(scalarArray, img)
IsGreen(scalarArray, img)
IsRed(scalarArray, img)
win.ShowImage(img)
}
func IsGreen(inputArray [4]float64, img *opencv.IplImage) {
// from http://www.rapidtables.com/web/color/RGB_Color.htm
// adjust the upper and lower to increase the range and sensitivity
greenUpper := [4]float64{210, 255, 199, 0} // Blue, Green, Red
greenLower := [4]float64{50, 80, 50, 0}
if (inputArray[0] >= greenLower[0]) && (inputArray[0] <= greenUpper[0]) {
if (inputArray[1] >= greenLower[1]) && (inputArray[1] <= greenUpper[1]) {
if (inputArray[2] >= greenLower[2]) && (inputArray[2] <= greenUpper[2]) {
fmt.Println("Green color detected.")
textFont.PutText(img, "I think it is green", opencv.Point{10, 50}, greenColor)
}
}
}
}
func IsRed(inputArray [4]float64, img *opencv.IplImage) {
// from http://www.rapidtables.com/web/color/RGB_Color.htm
// adjust the upper and lower to increase the range and sensitivity
redUpper := [4]float64{70, 75, 255, 0} // Blue, Green, Red
redLower := [4]float64{15, 15, 100, 0}
if (inputArray[0] >= redLower[0]) && (inputArray[0] <= redUpper[0]) {
if (inputArray[1] >= redLower[1]) && (inputArray[1] <= redUpper[1]) {
if (inputArray[2] >= redLower[2]) && (inputArray[2] <= redUpper[2]) {
fmt.Println("Red color detected.")
textFont.PutText(img, "I think it is red", opencv.Point{10, 50}, redColor)
}
}
}
}
func IsBlue(inputArray [4]float64, img *opencv.IplImage) {
// we will only consider navy blue, dark blue, medium blue and true blue
// from http://www.rapidtables.com/web/color/RGB_Color.htm
// adjust the upper and lower to increase the range and sensitivity
blueUpper := [4]float64{255, 175, 95, 0}
blueLower := [4]float64{128, 25, 25, 0}
if (inputArray[0] >= blueLower[0]) && (inputArray[0] <= blueUpper[0]) {
if (inputArray[1] >= blueLower[1]) && (inputArray[1] <= blueUpper[1]) {
if (inputArray[2] >= blueLower[2]) && (inputArray[2] <= blueUpper[2]) {
fmt.Println("Blue color detected.")
textFont.PutText(img, "I think it is blue", opencv.Point{10, 50}, blueColor)
}
}
}
}
func processFrameAndUpdate() {
for {
if webCamera.GrabFrame() {
IplImgFrame := webCamera.RetrieveFrame(1)
if IplImgFrame != nil {
// Have to make the image frame
// smaller, for performance reason - i.e speed
// the bigger the area, the slower it becomes...
IplImgFrame = opencv.Resize(IplImgFrame, 0, height-200, opencv.CV_INTER_LINEAR)
if filterOn == true {
detectColor(IplImgFrame)
} else {
win.ShowImage(IplImgFrame)
}
}
}
}
}
func main() {
cores := runtime.NumCPU()
// maximize CPU usage for maximum performance
runtime.GOMAXPROCS(cores)
fmt.Printf("This machine has %d CPU cores. Using all cores. \n", cores)
// a new OpenCV window
win = opencv.NewWindow("Go-OpenCV color recognition example")
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("Go-OpenCV color recognition 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("Go-OpenCV color recognition example")
framebox2 := gtk.NewVBox(false, 1)
frame2.Add(framebox2)
//--------------------------------------------------------
// GtkScale
//--------------------------------------------------------
scaleHBox := gtk.NewHBox(false, 1)
framebox2.PackStart(scaleHBox, false, false, 0)
vpaned.Pack2(frame2, false, false)
//--------------------------------------------------------
// GtkHBox
//--------------------------------------------------------
buttons := gtk.NewHBox(false, 1)
//--------------------------------------------------------
// GtkButton
//--------------------------------------------------------
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("Detect color")
combobox.AppendText("No color detection")
combobox.SetActive(0) // Detect color
combobox.Connect("changed", func() {
println("value:", combobox.GetActiveText())
if combobox.GetActiveText() == "Detect color" {
statusbar.Push(context_id, "Detecting color in region of interest (ROI).")
filterOn = true
} else {
statusbar.Push(context_id, "Not detecting color in region of interest (ROI).")
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, 85)
window.ShowAll()
gtk.Main()
}
References:
https://godoc.org/github.com/lazywei/go-opencv/opencv#Scalar
https://www.socketloop.com/tutorials/golang-integer-is-between-a-range
https://socketloop.com/tutorials/golang-put-utf8-text-on-opencv-video-capture-image-frame
http://docs.opencv.org/2.4.10/modules/core/doc/basic_structures.html
See also : Golang : Put UTF8 text on OpenCV video capture image frame
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
+5.9k Golang : Dealing with backquote
+9.6k Golang : Get current, epoch time and display by year, month and day
+8.7k Golang : Sort lines of text example
+6.1k Golang : Selection sort example
+5.4k Fix fatal error: evacuation not done in time problem
+6.2k Grep : How to grep for strings inside binary data
+6k Golang & Javascript : How to save cropped image to file on server
+9.2k Golang : Create unique title slugs example
+24.2k Golang : GORM read from database example
+21.9k Golang : Print leading(padding) zero or spaces in fmt.Printf?
+29.1k Golang : How to create new XML file ?
+23k Golang : Get ASCII code from a key press(cross-platform) example