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:

Golang OpenCV tell color name example

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